続)メンバー関数テンプレートの特殊化

結局main側のインタフェースを変えずにどう実装するかに着目した結果こうなった。


#include
#include
#include

// Widgetのfooから呼ばれる関数オブジェクトを作る
template
struct widget_foo
{
T operator ()(int i) {
T tmp;
std::stringstream ss;
ss << i;
ss >> tmp;
return tmp;
}
};

// intに特殊化したバージョン
template <>
struct widget_foo
{
int operator ()(int i)
{
return ++i;
}
};

class Widget
{
public:
template
T foo(int i)
{
widget_foo w;
return w(i); // Tに対応したwidget_fooのoperator()(int)を呼び出す
}
};

int main()
{
Widget w;
std::string s(w.foo(100));
int i = w.foo(100);
std::cout << "s:" << s << '\n';
std::cout << i << std::endl;

return 0;
}



結局クラスのメンバー関数での特殊化は諦めて外にテンプレート関数オブジェクトを作ってそっちを特殊化。
これでVCでもgccでもどっちでも動くコードの出来上がり。
え?Widgetにメンバー変数が増えてwidget_fooで使いたくなったらどうするかって?
# 誰も聞いてないかwでも趣味なので書いてみる


Widgetの変数を持つpimplクラスを作る



struct widget_pimpl
{
int add;
widget_pimpl() : add(2) {}
};

pimplクラスを受け取るためにoperatorに引数を追加


template
struct widget_foo
{
int operator ()(widget_pimpl* , int i) // widget_pimpl*を受け取る引数を追加
...同じなので省略
};

template <>
struct widget_foo
{
int operator ()(widget_pimpl* p, int i)
{
return i + p->add; // widget_pimplのメンバー変数を直接さわっちゃえ
}
};


widget_fooの第一引数にpimpl_ポインタを渡す。


class Widget
{
widget_pimpl* pimpl_; // pimplイディオム
public:
Widget() :pimpl_(0) {
try {
pimpl_ = new widget_pimpl;
} catch(...) {
}
}
~Widget() { delete pimpl; }

template
T foo(int i) {
widget_foo w;
return w(pimpl_, i); // ここが最初と違う
}
};



これでいいんじゃない?
もっと良い方法ないのかなぁ〜