使用lambdas进行C ++模板参数推导

时间:2014-04-04 11:29:16

标签: c++ templates c++11 lambda variadic-templates

我有以下模板声明

template<typename T>
void foo(function<void(T)> f){
    // ...
};

但是当我这样称呼它时

foo([](string s){ });
// visual studio 13 error message => 
// Error:  void foo(std::function<void(_Type)>)' : 
//could not deduce template argument for 'std::function<void(_Type)>' 
//from 'main::<lambda_58b8897709e10f89bb5d042645824f66>

模板参数推断失败。 为什么?如何解决?

我对可变参数模板有同样的问题

template<typename ... Tn>
void foo(function<void(Tn ...)> f){
    // ...
};

int main() {
    foo<string,bool>([](string s,bool b){ }); // Works
    foo([](string s,bool b){ }); // Fails
}

但是如果我明确地施放了lambda它就可以了(!)

foo((function<void(string,bool)>) [](string s,bool b){ }); // Works

// Or even a simpler syntax with a macro
#define lmda_(a) (function<void a>)[&] a
foo( lmda_((string s, bool b)) { }); // Works (note the extra () )

为什么模板参数推断失败?以及如何解决它?

2 个答案:

答案 0 :(得分:4)

这是一个不可推断的背景。无法推断出模板参数T

这是一个最简单的例子。给出:

 template<typename T>
 struct X
 {
     X(T t) : data(t) {}
     T data;
 };

 template<typename T>
 void f(X<T> param);

现在你正在做这样的事情:

 f(100);

认为T将推断为int。没有。它不会推断到int。因为T可能有多种可能性。例如,可能有专业化:

 template<>
 struct X<double>
 {
     X(int t) : data(t) {}
     int data;
 };

 template<>
 struct X<float> //another specialization
 {
     X(int t) : data(t) {}
     int data;
 };

即使tint(与100的类型相同),模板参数可以是doublefloat(或任何其他类型)。

答案 1 :(得分:0)

标准库函数是一种可以容纳任何对象的类型 可以使用调用operator()调用,这意味着它以其他方式  函数类型的对象是一个函数对象。

在函数实例化期间foo([](string str){}); 编译器无法推断出&#34;函数&#34;的类型。函数对象类 通过这种方式,我们明确指定了导致描述函数依赖关系的更简洁方式的类型。     auto func1 = [](string str){};     FOO(func1的);     要么     foo([](string str){});