1

私は現在、関数テンプレートでいっぱいの 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);

これは、この問題を解決するための最良のアプローチですか? 私が見る唯一の欠点は、関数テンプレートに適切なデフォルトを持つ多くのパラメーターが含まれている場合、多くの単純な転送関数を導入できる可能性があることです。

4

3 に答える 3

5

あなたの転送機能は完全に適切なソリューションだと思いますが、あなたのソリューションでは、テンプレート パラメーターを明示的に指定する必要はありませんか? (0 は任意の型に変換できる整数定数ですV*。) またdoWordvs doWork?

原則として、あまり効果のないオプション パラメータは使用しないようにしてください。

テンプレートの 2 つのパラメーター バージョンと 3 つのパラメーター バージョンの両方をサポートするために多くの余分なメカニズムを追加するよりも、関数のクライアントに if appriopriate を追加するように強制する方が簡単な場合があります。, (void*)0ただし、それは予想される用途に依存します。

于 2009-10-11T19:37:54.263 に答える
2

クライアント コードの観点からすると、3 番目のパラメーターがない場合、なぜそれを作成する必要があるのでしょうか?

したがって、使いやすさと読みやすさを目指すなら、ラッパーの方法に同意します。それは完全に理にかなっていて、作成したラッパーは、必要な3番目のパラメーターの適切な値を担当し ます

さらに、必要に応じて、さまざまな専門分野に別のデフォルトを使用することができます。

于 2009-10-11T20:03:46.177 に答える
0

1 つの可能性は、テンプレート引数を並べ替えて、オプションの引数が最初になるようにすることです。

template <typename V, typename T, typename U>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);

doWork<void>('a', text); 

転送もOKのようです。

ただし、デフォルトの引数とテンプレートはうまく一致していないようです。

于 2009-10-11T19:56:52.340 に答える