C++如何使用默认参数指定模板化类的所有朋友?

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>,但后者当然不起作用.

如果我使用的术语不正确,请道歉.

Xeo*_*Xeo 8

我可以想象有一种更短的方式来表示为所有可能的ClassImplType枚举值定义了朋友.

可悲的是,确实没有.你可以试试

template<ClassImplType I> friend class graph<T, I>;
Run Code Online (Sandbox Code Playgroud)

但标准只是禁止一个人与部分专业化合作:

§14.5.4 [temp.friend] p8

朋友声明不得声明部分专业化.[ 例如:

template<class T> class A { };
class X {
  template<class T> friend class A<T*>; // error
};
Run Code Online (Sandbox Code Playgroud)

- 末端的例子 ]

你只能和他们交朋友:

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)

实例.


Pub*_*bby 6

您可以模拟friend语句:

template<typename U, ClassImplType  V>
friend class graph_foo;
Run Code Online (Sandbox Code Playgroud)

我正在试图弄清楚如何保持T- 如果我发现我会更新.