【问题标题】:Passkey pattern for template class, problem with friend and template template parameter模板类的密钥模式,朋友和模板模板参数的问题
【发布时间】:2021-09-11 18:04:18
【问题描述】:

这是经典的“密码”模式,它允许函数只能在特定类的范围内访问:

#include <iostream>

template <typename T>
class passkey {
private:
  friend T;
  passkey() {}

  // noncopyable
  passkey(const passkey&) = delete;
  passkey& operator=(const passkey&) = delete;
};

struct A {
    A();
};

void g(int i, passkey<A>) {
    std::cout << i;
}

A::A(){g(42,{});} 

int main() {

    A a;

    return 0;
}

这里的函数g只能在A内调用。但是如果A 现在是一个模板类,是否可以扩展它?下面的 sn-p 不能编译(用clang,但它用gcc...),因为对于模板朋友来说,似乎必须使用一个详细说明符,这似乎导致声明冲突...

#include <iostream>

template <template<typename...> class T>
class passkey {
private:
  template<typename...> friend class T;
  passkey() {}

  // noncopyable
  passkey(const passkey&) = delete;
  passkey& operator=(const passkey&) = delete;
};

template<typename T>
struct A {
    A();
};

void g(int i, passkey<A>) {
    std::cout << i;
}

template<typename T>
A<T>::A(){g(42,{});} 

int main() {

    A<void> a;

    return 0;
}

这给出了铿锵声:

>source>:6:38: error: declaration of 'T' shadows template parameter
  template<typename...> friend class T;
                                     ^
<source>:3:39: note: template parameter is declared here
template <template<typename...> class T>

有什么诀窍可以让它发挥作用吗?

【问题讨论】:

    标签: c++ templates variadic-templates friend


    【解决方案1】:

    我很惊讶你的可变参数模板实际上是用 GCC 编译的。这就是我实际写它的方式:

    template <template<typename... Ts> class T, typename... Ts>
    class passkey {
      private:
        friend class T<Ts...>;
    
        constexpr passkey() {
          return;
        }
        passkey(passkey const&) = delete;
        passkey& operator=(passkey const&) = delete;
    };
    

    此外,我会让函数 g 获取 r 值引用并使用 std::move 显式调用它。

    Try it here!

    【讨论】:

    • 但是,你只允许特定的A作为A&lt;void&gt;,而不是A&lt;int&gt;,或者你还需要制作g模板。
    • @Jarod42 是的,当然,但这不是 OP 试图用他的代码做的吗?
    • 我理解为“任何A 的密码”。添加Ts... 几乎没有用,因为您可以直接将template &lt;typename T&gt; void g(int i, passkey&lt;A&lt;T&gt;&gt;) 与第一个sn-p 一起使用。
    • @Jarod42 目前尚不清楚 OP 想用Ts... 做什么。如果您稍后不使用Ts...,那么很明显,不需要可变模板,但是如果您打算在passkey 中使用Ts...,那么我的方法确实很有用。此外,我非常怀疑像template&lt;typename...&gt; friend class T; 这样让你与任何T&lt;...&gt; 成为朋友的东西实际上是合法的C++。 ICC 和 MVSC 也会投诉。
    • passkey 中硬编码A 被接受。 Demo。据我了解,OP 想要通用。
    猜你喜欢
    • 2013-09-28
    • 2014-10-03
    • 2017-08-08
    • 1970-01-01
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多