バリデーションテンプレートへの私の最初のベンチャーでは、テンプレート引数のすべての組み合わせで派生クラスをインスタンス化する関数を作成しようとしています。実行時オプションクラスを使用するというアイデアは、使用する正確なテンプレートのインスタンス化を選択できることになります。私は1と2のテンプレート引数で動作するベースケースを得ることができました。しかし、一般的なケースが動作していない、以下SelectInstanceの第三の呼び出しは次のエラーでコンパイルに失敗します。ランタイム値をランタイム値をコンパイルテンプレート引数に変換する複数のパラメータパックの操作
candidate function not viable: requires 3 arguments, but 2 were provided AbstractBase *SelectInstance(Func func, Args... args)
完全なコード以下の通りです:
#include <memory>
#include <iostream>
struct Options
{
bool GetFirstParameter() { return true; }
bool GetSecondParameter() { return false; }
bool GetThirdParameter() { return true; }
};
struct AbstractBase
{
virtual void PrintMe() = 0;
};
template<class... Args>
struct Derived : public AbstractBase
{
virtual void PrintMe() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
template<class... Args>
AbstractBase *SelectInstance()
{
return new Derived<Args...>();
}
template<class Func, class... UnpackedArgs>
AbstractBase *SelectInstance(Func func)
{
if (func())
return SelectInstance<float, UnpackedArgs...>();
else
return SelectInstance<double, UnpackedArgs...>();
}
template<class Func, class... Args, class... UnpackedArgs>
AbstractBase *SelectInstance(Func func, Args... args)
{
if (func())
return SelectInstance<Args..., float, UnpackedArgs...>(args...);
else
return SelectInstance<Args..., double, UnpackedArgs...>(args...);
}
int main()
{
Options opts;
std::unique_ptr<AbstractBase> one(
SelectInstance(
std::bind(&Options::GetFirstParameter, &opts)
)
);
one->PrintMe();
std::unique_ptr<AbstractBase> two(
SelectInstance(
std::bind(&Options::GetFirstParameter, &opts),
std::bind(&Options::GetSecondParameter, &opts)
)
);
two->PrintMe();
// this one fails to compile!
std::unique_ptr<AbstractBase> three(
SelectInstance(
std::bind(&Options::GetFirstParameter, &opts),
std::bind(&Options::GetSecondParameter, &opts),
std::bind(&Options::GetThirdParameter, &opts)
)
);
three->PrintMe();
}
私はおそらく可変長を悪用していますファンクタを新しいパラメータパックに変換するためのテンプレートが不適切です。どんな指導も高く評価されます。
ありがとうございました。余分な過負荷を書いたら、間違った道を歩いているように感じました。これを "SelectInstance"に反転して、アンパックの順序を引数として渡されたファンクタと同じに保ちました。 –