template な friend

テンプレートクラスや関数を friend にする方法のメモ.危険性についても言及.

方法

こんな感じで書く:

class TTest
{
  ...
  template<typename T> friend void Func(TTest &test,const T &x);
}

サンプル:

#include <iostream>

class TTest
{
public:
  TTest() : x(-1) {}
  const int& X() const {return x;}
private:
  int x;
  template<typename T> friend void Func(TTest &test,const T &x);
};

template<typename T> void Func(TTest &test,const T &x)
{
  test.x= x;
}

using namespace std;
#define print(var) std::cout<<#var"= "<<(var)<<std::endl
int main(int argc, char**argv)
{
  TTest test;
  print(test.X());
  Func(test,3.14);
  print(test.X());
  return 0;
}

結果:

test.X()= -1
test.X()= 3

危険性

しかし,通常の friend 関数やクラスと比べて,テンプレート関数やクラスを friend にすると危険性が増す
つまり,ユーザが friend 関数やクラスを特殊化したものを定義できる可能性がある.
例えば,上のコードに,ユーザは

template<> void Func(TTest &test,const int &x)
{
  test.x= 100000;
}

という特殊化を(悪意を持って)追加できる.