首页 > 解决方案 > 模板类的密钥模式,朋友和模板模板参数的问题

问题描述

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

#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现在是模板类,是否可以扩展它?以下代码段无法编译(使用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++templatesvariadic-templatesfriend

解决方案


我很惊讶你的可变参数模板实际上是用 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显式调用它。

在这里试试!


推荐阅读