2014-04-04 253 views
2

模板参数推导,我有以下模板声明C++与lambda表达式

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 
} 

同样的问题,但是,如果我明确地转换它的工作拉姆达(!)

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()) 

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

+0

http://stackoverflow.com/q/11500881/560648 –

+1

这应该工作,并且可能是更好... 的#define lmda_(......)(函数<空隙(__VA_ARGS __)>)[&](__VA_ARGS__) - > foo(lmda_(string s,bool b){}); e:你需要使用两个下划线前后缀va_args(它们在这里变成粗体格式文本) – Shaggi

+0

*机器人的Lambda平庸定律*:如果你的设计关心lambda表达式,那就错了。 (也简称为“lambda不是特别的”) –

回答

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(或任何其他类型)。

+0

也许你的意思是'f({100});'。 – Constructor

+0

@Constructor:编辑删除混乱!谢谢。 – Nawaz

0

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

函数实例化期间foo([](string str){}); 编译器没有办法为“函数”函数对象类推导出T的类型 这样我们就明确指定了导致用于描述函数的依赖关系的更好方式的类型。 auto func1 = [](string str){}; foo(func1); 或 foo([](string str){});