今日のテーマは、Visual C++だけでコンパイル・実行できる不思議なコードです。(nullptrさえ直せば)2005から2013までいずれでも通用します。
#include <iostream> void f() { std::cout << "f" << std::endl; } void g() { std::cout << "g" << std::endl; } template<class T> class TypeF { friend void InvokeImpl(T*) { f(); } }; template<class T> class TypeG { friend void InvokeImpl(T*) { g(); } }; template<class T> class Selector { friend void InvokeImpl(T*); public: static void Invoke() { return InvokeImpl(static_cast<T*>(nullptr)); } }; // ここから利用例 struct Hoge; struct Piyo; struct Fuga; template class TypeF<Hoge>; template class TypeG<Piyo>; template class TypeF<Fuga>; int main() { Selector<Hoge>::Invoke(); Selector<Piyo>::Invoke(); Selector<Fuga>::Invoke(); } |
これを実行するとこういう出力になります。
f g f
このコードは「型によって関数fとgを呼び分ける」というものです。
利用者は、自分の作った型を実引数にTypeFまたはTypeGを明示的実体化します。Selector::Invokeに型を与えて呼び出すと、明示的実体化したほうのInvokeImplが呼び出されるというからくりです。このtemplateとfriendの組み合わせ方がGCCやClangではうまくいきませんでした。
これに相当することをやるだけなら、ほかにやりよう(GCCでもClangでもできる方法)はあります。単にこういう方法もあるという紹介でした。
スポンサード リンク |