2017-02-13 14 views
6
以下の可変長引数テンプレートを考える

テンプレート控除

template<typename... Params> 
void fun(void(*f)(Params...), Params... params) { 
    f(params...); 
} 

int main() { 
    fun(+[](int a, int b) {}, 2, 3); 
} 

今、私は明示的にすべてのラムダの引数の型を指定する必要がラムダでfunを呼び出すときのために。 int, int2, 3から導き出される可能性があるため、冗長なようです。より簡潔に自動化する方法はありますか?

私は仕事に次のようになるが、それはしていません:

template<typename... Params> 
void fun(void(*f)(Params...), Params... params) { 
    f(params...); 
} 

int main() { 
    fun(+[](auto a, auto b) {}, 2, 3); 
} 

私はg++ 5.4.0-std=c++14でコンパイルしています。

+1

あなたは 'auto'の代わりに' int'とタイプすることに問題がありますか? – Brian

+0

@Brianはい、私はそれが 'int'であると推論する必要があります。より劇的なものにすることは、何でもできます。 –

答えて

3

Tではなく、ポインタで機能を取る:その方法

template<typename T, typename... Params> 
void fun(T f, Params... params) { 
    f(params...); 
} 

int main() { 
    fun([](auto a, auto b) {}, 2, 3); 
} 

、コンパイラは+オペレータ内部の場合代わりに呼び出しサイトでコールする権利である過負荷を選択することができます。コメントの中で述べたように、とにかく汎用ラムダには+オペレータが定義されていません。


また、あなたはアイデンティティの別名を使用して関数ポインタからParamsを推測しようとするから、コンパイラを無効にすることができますが、私は実際にそれをお勧めしません。とにかく、ここに行く:

template<typename T> 
struct identity { using type = T; }; 

template<typename T> 
using identity_t = typename identity<T>::type; 

template<typename... Params> 
void fun(void(*f)(identity_t<Params>...), Params... params) { 
    f(params...); 
} 

int main() { 
    // v----- no unary +. That operator is not defined for generic lambdas. 
    fun([](auto a, auto b) {}, 2, 3); 
} 
+0

非genericラムダの '+'演算子もないことに注意してください。ビルトインされた '+ '演算子が使用されますが、ラムダは変換演算子を使用してポインタに強制的に変換されます。 – Brian

関連する問題