2

I have the following template declaration

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

But when i call it like this

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 argument deduction fails . Why? how to fix it?

I have the same problem with variadic templates

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
}

But if i explicitly cast the lambda it works (!)

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

Why template argument deduction fails ? and how to fix it?

Cœur
  • 37,241
  • 25
  • 195
  • 267
amin
  • 3,672
  • 5
  • 33
  • 61
  • http://stackoverflow.com/q/11500881/560648 – Lightness Races in Orbit Apr 04 '14 at 11:41
  • 1
    This should work, and might be nicer… #define lmda_(…) (function)[&] (__VA_ARGS__) -> foo( lmda_(string s, bool b) { }); // notice the missing () e: you need to pre- and postfix va_args with 2 underscores (they turn into bold formatted text here) – Shaggi Apr 04 '14 at 11:48
  • *Robot's Law of Lambda Banality*: if your design cares about lambdas, it's wrong. (Also phrased simply as "lambdas are not special") – R. Martinho Fernandes Apr 04 '14 at 12:33

2 Answers2

4

That is a non-deducible context. The template parameter T cannot be deduced.

Here is a simplest example. Given:

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

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

Now you're doing something like this:

 f(100);

thinking that T will be deduced to int. NO. It will not be deduced to int. Because there could be more than one possibility for T. For example, there might be specializations as:

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

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

So even though t is int (same as the type of 100), the template argument could be double or float (or any other type).

Nawaz
  • 353,942
  • 115
  • 666
  • 851
0

The standard-library function is a type that can hold any object you can invoke using the call operator () which means in other ways that it is an object of type function is a function object.

During function instantiation foo([] (string str){}); There is no way the compiler would deduce the type of T for the "function" function object class This way we explicitly specify the type which leads to neater way of describing the dependencies for the function. auto func1 =[](string str){}; foo(func1); or foo([] (string str){});