Ann*_*sum 12 c++ templates arguments friend
要使用默认参数定义模板化类的朋友,是否需要在下面的代码中指定所有朋友(哪个有效)?
// Different class implementations
enum ClassImplType { CIT_CHECK, CIT_FAST, CIT_GPU, CIT_SSE, CIT_NOF_TYPES } ;
// Graph class has default template argument CIT_CHECK
template <typename T, ClassImplType impl_type = CIT_CHECK>
class graph {
//...
};
// Vertex class
template <typename T>
class vertex {
//...
friend class graph<T, CIT_CHECK>;
friend class graph<T, CIT_FAST>;
friend class graph<T, CIT_GPU>;
friend class graph<T, CIT_SSE>;
};
Run Code Online (Sandbox Code Playgroud)
我可以想象有一种更短的方式来表示为所有可能的ClassImplType枚举值定义了朋友.有点像friend class graph<T, ClassImplType>,但后者当然不起作用.
如果我使用的术语不正确,请道歉.
我可以想象有一种更短的方式来表示为所有可能的ClassImplType枚举值定义了朋友.
可悲的是,确实没有.你可以试试
template<ClassImplType I> friend class graph<T, I>;
Run Code Online (Sandbox Code Playgroud)
但标准只是禁止一个人与部分专业化合作:
§14.5.4 [temp.friend] p8
朋友声明不得声明部分专业化.[ 例如:
Run Code Online (Sandbox Code Playgroud)template<class T> class A { }; class X { template<class T> friend class A<T*>; // error };- 末端的例子 ]
你只能和他们交朋友:
template<class U, ClassImplType I>
friend class graph;
Run Code Online (Sandbox Code Playgroud)
或者特定的一个:
friend class graph<T /*, optional-second-arg*/>;
Run Code Online (Sandbox Code Playgroud)
我不明白所有可能的专业化如何在这里引起问题,说实话,但让我们假设它确实如此.我知道的一种解决方法是使用密钥模式,虽然我们将使用略微缩减的版本(我们不能在allow这里使用该机制,因为它不能很好地允许访问模板的所有特化):
template<class T>
class passkey{
passkey(){}
friend T;
// optional
//passkey(passkey const&) = delete;
//passkey(passkey&&) = delete;
};
// Different class implementations
enum ClassImplType { CIT_CHECK, CIT_FAST, CIT_GPU, CIT_SSE, CIT_NOF_TYPES } ;
template<class> struct vertex;
// Graph class has default template argument CIT_CHECK
template <typename T, ClassImplType impl_type = CIT_CHECK>
class graph {
public:
void call_f(vertex<T>& v){ v.f(passkey<graph>()); }
//...
};
// Vertex class
template <typename T>
class vertex {
//...
public:
template<ClassImplType I>
void f(passkey<graph<T,I>>){}
};
Run Code Online (Sandbox Code Playgroud)
您将注意到您需要创建graph需要访问public的所有功能,但由于passkeys只能由指定的特化创建,因此这不是问题graph.
您还可以进一步创建一个可用于访问顶点功能的代理类(仅graph更改):
// Graph class has default template argument CIT_CHECK
template <typename T, ClassImplType impl_type = CIT_CHECK>
class graph{
typedef passkey<graph> key;
// proxy for succinct multiple operations
struct vertex_access{
vertex_access(vertex<T>& v, key k)
: _v(v), _key(k){}
void f(){ _v.f(_key); }
private:
vertex<T>& _v;
key _key;
};
public:
void call_f(vertex<T>& v){
vertex_access va(v, key());
va.f(); va.f(); va.f();
// or
v.f(key());
}
//...
};
Run Code Online (Sandbox Code Playgroud)
您可以模拟friend语句:
template<typename U, ClassImplType V>
friend class graph_foo;
Run Code Online (Sandbox Code Playgroud)
我正在试图弄清楚如何保持T- 如果我发现我会更新.