2017-02-13 146 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, int可以从2, 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

你有一个问题,键入'int'而不是'auto'? – 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); 
} 

这样,编译器可以选择重载是在调用点,而不是如果+运营商内部调用正确的。正如在评论中所说的那样,无论如何也没有为泛型lambdas定义的运算符+


或者,你可以尝试使用身份别名来推断从函数指针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

请注意,非通用lambdas也没有'+'运算符。内置的'+'操作符被使用,但拉姆达由此强制转换为使用其转换运算符为一个函数指针的指针。 – Brian