模板类的密钥模式,友元和模板模板参数的问题



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

#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>

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

我很惊讶你的varadic模板居然用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调用它。

在这里试试!

最新更新