2011-11-25 22 views
10

私は、CとC++の間のインタフェースで例外ファイアウォールとして機能するバリデーションテンプレートを使用しています。テンプレートは単純に関数をとり、その後にN個の引数をとり、try catchブロック内で関数を呼び出します。これはうまくいきました。残念ながら、私が今呼びたい関数の1つが追加のデフォルト引数をとります。その結果、関数名は解決されず、テンプレートはコンパイルに失敗します。Variadic Templates、デフォルトの引数を持つ関数への完璧な転送

エラーは次のとおりです。次のように

perfect-forward.cpp: In function ‘void FuncCaller(Func, Args&& ...) [with Func = void (*)(const std::basic_string<char>&, double, const std::vector<int>&), Args = {const char (&)[7], double}]’ :
perfect-forward.cpp:69:41: instantiated from here
perfect-forward.cpp:46:4: error: too few arguments to function

コードの簡易版は、次のとおりです。

template< class Func, typename ...Args > 
void FuncCaller(Func f, Args&&... params) 
{ 
    try 
    { 
     cout << __func__ << " called\n"; 
     f(params...); 
    } 
    catch(std::exception& ex) 
    { 
     cout << "Caught exception: " << ex.what() << "\n"; 
    } 
} 

void Callee(const string& arg1, double d, const vector<int>&v = vector<int>{}) 
{ 
    cout << __func__ << " called\n"; 
    cout << "\targ1: " << arg1 << "\n"; 
    cout << "\td: " << d << "\n"; 
    cout << "\tv: "; 
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " " )); 
    cout << "\n"; 
} 

int main() 
{ 
    vector<int> v { 1, 2, 3, 4, 5 }; 

    FuncCaller(Callee, "string", 3.1415, v); 
    FuncCaller(Callee, "string", 3.1415); **// Fails to compile** 

    return 0; 
} 

は、このコードの動作は、万一または私は、コンパイラからあまり期待していますか?

注:2でcfollowingコンストラクタを呼び出すときに

template<typename TypeToConstruct> struct SharedPtrAllocator 
{ 
    template<typename ...Args> shared_ptr<TypeToConstruct> 
     construct_with_shared_ptr(Args&&... params) { 
     return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...)); 
    }; 
}; 

作品:私はデフォルト引数とコードがコンパイルされ、期待通りに動作しますが、

すなわちを持つコンストラクタで完璧な転送の使用をテストしていますまたは3つの引数...

MyClass1(const string& arg1, double d, const vector<int>&v = vector<int>{}) 
+2

(ちなみに 'f(std :: forward (params)...) ')です。 –

答えて

8

私はこれが達成できる方法はないと思います。デフォルトの引数値は、関数シグネチャの一部ではありません。関数を文字通り呼び出すと、コンパイラによって展開されるコード生成のショートハンドだけです。同様に、std::bindもデフォルトの引数を取りません。

+1

私はそれが長いと思っていました。既定の引数を持つコンストラクタは機能しますか? – mark

+1

さて、関数を直接呼び出すことができます。これは、コードが行うことです(すべてのテンプレートパラメータの置換を解く場合)。しかし、元の質問では、関数型自体が推論され、それがデフォルトの引数を失う場所です。 –

関連する問題