次のタグディスパッチコードがあります(LiveWorkSpaceを参照)
#include <iostream>
// traits types
struct A {}; struct B {}; struct C {};
// helpers
void fun_impl(bool, A) { std::cout << "A\n"; }
void fun_impl(bool, B) { std::cout << "B\n"; }
// would like to eliminate this
void fun_impl(bool b, C)
{
if(b)
fun_impl(b, A());
else
fun_impl(b, B());
}
template<typename T>
void fun(bool b, T t)
{
// T = A, B, or C
fun_impl(b, t);
}
int main()
{
fun(true, A()); // "A"
fun(false, A()); // "A"
fun(true, B()); // "B"
fun(false, B()); // "B"
fun(true, C()); // "A"
fun(false, C()); // "B"
}
ただし、このタグのディスパッチは関数と密接に結びついており、fun
これを使用するすべての関数に対してこのタグのディスパッチを実装するには、3 つのヘルパー関数を維持する必要があります。
引数推定失敗:関数オブジェクトfun_impl
のテンプレート パラメーターに抽象化しようとしましたが、引数として渡すと、2 つのオーバーロードのどちらが必要かを推定できません。mixed_dispatch
fun_impl
template<typename T>
struct mixed_dispatch
{
template<typename Fun>
void operator()(Fun f, bool b)
{
return f(b, T());
}
};
template<>
struct mixed_dispatch<C>
{
template<typename Fun>
void operator()(Fun f, bool b)
{
if (b)
return f(b, A());
else
return f(b, B());
}
};
template<typename T>
void fun(bool b, T)
{
// T = A, B, or C
mixed_dispatch<T>()(fun_impl, b); // ERROR: Fun cannot be deduced
}
質問: 呼び出される関数からタグ ディスパッチを分離する他の方法はありますか?
C++11 可変個引数テンプレート/Boost.Fusion または現在のコードを簡素化するその他のウィザードリィを使用する提案を受け入れます (この特定のディスパッチを使用するすべての関数に対して、2 つの代わりに 3 つのヘルパー関数を維持する必要があります。複雑なディスパッチにより、ヘルパー関数の数がさらに速くなります)。