私は現在、関数テンプレートでいっぱいの API の整理に取り組んでおり、次のコードを書きたいという強い願望がありました。
template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);
このテンプレートを呼び出すときは、次のようにしたいと思います。
std::string text("hello");
doWork(100, 20.0, &text);
doWork('a', text); // oops!
doWork<char, std::string, void>('a', text); // to verbose!
残念ながら、コンパイラはオプションのパラメータの型を推測できないため、2 番目の呼び出しはコンパイルされません。これは残念なことです。なぜなら、私はパラメーターの型が何であるかはあまり気にせず、その値が NULL であることを気にしているからです。また、3 回目の呼び出しのルートは可読性を損なうので避けたいと思います。
これにより、テンプレート引数にデフォルトの型を持たせようとしましたが、V
(少なくとも VC++ 9.0 を使用して) 関数テンプレートの引数にデフォルトの型を適用できないため、これも機能しません。
template <typename T, typename U, typename V = void> // oops!
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);
私の残りの唯一のオプションはdoWork
、テンプレート引数について何も知らない のオーバーロードを導入することV
です。
template <typename T, typename U>
void doWork(const T& arg1, const U& arg2)
{
doWork(arg1, arg2, 0);
}
template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg);
これは、この問題を解決するための最良のアプローチですか? 私が見る唯一の欠点は、関数テンプレートに適切なデフォルトを持つ多くのパラメーターが含まれている場合、多くの単純な転送関数を導入できる可能性があることです。