319

In C++11, is there a way to template a lambda function? Or is it inherently too specific to be templated?

I understand that I can define a classic templated class/functor instead, but the question is more like: does the language allow templating lambda functions?

5
  • Is there a use case where a lambda template would be useful? Commented Aug 26, 2010 at 14:15
  • 13
    James: You could build a function to iterate over a tuple (Not necessarily useful). Commented Aug 26, 2010 at 17:04
  • I thought of the idea while reading an interview of Stroustrup talking about meta-template complexity being a problem. If it was allowed, I was imagining the ninja code-fu that might be invented by too clever programmers playing with this features combination... Commented Aug 26, 2010 at 19:26
  • 2
    Funny to see historical opinions from a decade ago. Commented Jun 11, 2021 at 18:32
  • Indeed. Now I see how that can be useful. I also can see how it can be abused, but all useful tools can be. :grimacing: Commented Jun 16, 2021 at 18:10

14 Answers 14

225

UPDATE 2018: C++20 will come with templated and conceptualized lambdas. The feature has already been integrated into the standard draft.


UPDATE 2014: C++14 has been released this year and now provides Polymorphic lambdas with the same syntax as in this example. Some major compilers already implement it.


At it stands (in C++11), sadly no. Polymorphic lambdas would be excellent in terms of flexibility and power.

The original reason they ended up being monomorphic was because of concepts. Concepts made this code situation difficult:

template <Constraint T>
void foo(T x)
{
    auto bar = [](auto x){}; // imaginary syntax
}

In a constrained template you can only call other constrained templates. (Otherwise the constraints couldn't be checked.) Can foo invoke bar(x)? What constraints does the lambda have (the parameter for it is just a template, after all)?

Concepts weren't ready to tackle this sort of thing; it'd require more stuff like late_check (where the concept wasn't checked until invoked) and stuff. Simpler was just to drop it all and stick to monomorphic lambdas.

However, with the removal of concepts from C++0x, polymorphic lambdas become a simple proposition again. However, I can't find any proposals for it. :(

Sign up to request clarification or add additional context in comments.

7 Comments

Simple... except there's a desire to reintroduce concepts and avoid features that make them complicated.
I think I'd rather have polymorphic lambdas than concepts. I don't understand how the example motivates anything; you could simply forbid it as an error, and require the lambda be monomorphic [](T x) {} or a constrained template []template<Constraint T>(T x) {}, which can be statically verified to match. Is there some reason why this wasn't possible?
You don't have to choose between concepts and polymorphic lambdas: cpp-next.com/archive/2011/12/a-breakthrough-for-concepts
Here is the proposal for polymorphic lambdas: open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf and the toy implementation in clang: faisalv.github.com/clang-glambda
Polymorphic Lambdas will be in C++14, at least they are in the Community Draft by now :)
|
123

In C++20 this is possible using the following syntax:

auto lambda = []<typename T>(T t){
    // do something
};

6 Comments

Does this mean we'll be able to write a lambda like this now []<>(){}?
In 2025, I use Clang compiler to write auto lambda = []<>(){}; and it said "lambda template parameter list cannot be empty". So, at least auto lambda = []<typename>(){};.
If you need to explicitly specify the template arguments when calling a lambda, which I find is a common need in my use cases (e.g. if the T t parameter didn’t exist in the example above), then you can do so using this syntax: lambda.template operator()<int>(). See stackoverflow.com/questions/49392738 for more info.
@Arda why can't we have something lambda<int>(). Is there a technical limitation to this?
@tartaruga_casco_mole The lambda is a function object. To use the template angle brackets you need a type (or a constexpr template). I assume that per the specification the compiler will have to treat the < in your example as a less than operator on the lambda object which will obviously fail. A future C++ version might allow for a templated operator() to be called in this way.
@tartaruga_casco_mole interestingly, it is possible to make ambiguous syntax if that did work: lambda<a>(b) could either be lambda.operator()<a>(b) or lambda.operator<(a).operator>(b)
56

As others have said, you can have template arguments in C++20 lambdas.

auto doSomething = []<typename T>(T x) {
    // blabla
};

However, other answers forget to tell you how to call those lambdas.

In the previous example it's easy because all template types can be deduced from the provided parameters.

doSomething(2);

But the problem comes when template types can NOT be deduced from the parameters.

auto readValue = [&buffer]<typename T>() -> T{
    return *(const T*)buffer;
};

You would expect to call it just like a regular templated function:

readValue<int>(); // WRONG!

But this does NOT compile. You have to write it like this:

readValue.template operator()<int>(); // VALID!

6 Comments

THANK YOU ! This was driving me nuts... The first type of call not working has to be some kind of oversight, right ?
@nick Sorry, I don't understand your question, what code are you refering to?
This one: readValue<int>(); This is what any sane person would try first and expect to work, right ? And i mean oversight as in by the C++ designers or committee.
Ah, I understand now. Well, I'm not sure why they made it the way it is. However, this is not specific to lambdas. Lambdas are syntatic sugar for structs with an operator(). As such, this problem is carried over there: godbolt.org/z/Evah16z5T
@Brandon readValue.template operator()<5>();
|
39

C++11 lambdas can't be templated as stated in other answers but decltype() seems to help when using a lambda within a templated class or function.

#include <iostream>
#include <string>

using namespace std;

template<typename T>
void boring_template_fn(T t){
    auto identity = [](decltype(t) t){ return t;};
    std::cout << identity(t) << std::endl;
}

int main(int argc, char *argv[]) {
    std::string s("My string");
    boring_template_fn(s);
    boring_template_fn(1024);
    boring_template_fn(true);
}

Prints:

My string
1024
1

I've found this technique is helps when working with templated code but realize it still means lambdas themselves can't be templated.

1 Comment

T would work fine in place of decltype(t) in this example.
29

In C++11, lambda functions can not be templated, but in the next version of the ISO C++ Standard (often called C++14), this feature will be introduced. [Source]

Usage example:

auto get_container_size = [] (auto container) { return container.size(); };

Note that though the syntax uses the keyword auto, the type deduction will not use the rules of auto type deduction, but instead use the rules of template argument deduction. Also see the proposal for generic lambda expressions(and the update to this).

1 Comment

The rules of auto type deduction are specifically defined to be the same as those of template function argument deduction.
10

I am aware that this question is about C++11. However, for those who googled and landed on this page, templated lambdas are now supported in C++14 and go by the name Generic Lambdas.

[info] Most of the popular compilers support this feature now. Microsoft Visual Studio 2015 supports. Clang supports. GCC supports.

Comments

8

I wonder what about this:

template <class something>
inline std::function<void()> templateLamda() {
  return [](){ std::cout << something.memberfunc() };
}

I used similar code like this, to generate a template and wonder if the compiler will optimize the "wrapping" function out.

1 Comment

What compiler? Did it?
5

There is a gcc extension which allows lambda templates:

// create the widgets and set the label
base::for_each(_widgets, [] <typename Key_T, typename Widget_T>
                         (boost::fusion::pair<Key_T, Widget_T*>& pair) -> void {
                             pair.second = new Widget_T();
                             pair.second->set_label_str(Key_T::label);
                          }
              );

where _widgets is a std::tuple< fusion::pair<Key_T, Widget_T>... >

1 Comment

FWIW, this has become standard syntax in C++20.
4

I've been playing with the latest clang version 5.0.1 compiling with the -std=c++17 flag and there is now some nice support for auto type parameters for lambdas:

#include <iostream>
#include <vector>
#include <stdexcept>

int main() {
    auto slice = [](auto input, int beg, int end) {
        using T = decltype(input);
        const auto size = input.size();
        if (beg > size || end > size || beg < 0 || end < 0) {
            throw std::out_of_range("beg/end must be between [0, input.size())");
        }
        if (beg > end) {
            throw std::invalid_argument("beg must be less than end");
        }
        return T(input.begin() + beg, input.begin() + end);
    };
    auto v = std::vector<int> { 1,2,3,4,5 };
    for (auto e : slice(v, 1, 4)) {
        std::cout << e << " ";
    }
    std::cout << std::endl;
}

Comments

3

Have a look at Boost.Phoenix for polymorphic lambdas: http://www.boost.org/doc/libs/1_44_0/libs/spirit/phoenix/doc/html/index.html Does not require C++0x, by the way :)

2 Comments

I already know about it but the question is exactly about the new standard anyway ;)
Ok :) C++0x lambdas are monomorphic and can't be templated, unfortunately.
2

I'm not sure why nobody else has suggested this, but you can write a templated function that returns lambda functions. The following solved my problem, the reason I came to this page:

template <typename DATUM>
std::function<double(DATUM)> makeUnweighted() {
  return [](DATUM datum){return 1.0;};
}

Now whenever I want a function that takes a given type of argument (e.g. std::string), I just say

auto f = makeUnweighted<std::string>()

and now f("any string") returns 1.0.

That's an example of what I mean by "templated lambda function." (This particular case is used to automatically provide an inert weighting function when somebody doesn't want to weight their data, whatever their data might be.)

2 Comments

This only work if you know the type of the argument fo the lambda before creating the lambda, in which case you can just use a lambda with the specific type as argument. The point of polymorphic lambda is to provide work to be done on an argument type you never know when you write the work code. Basically, this is totally different, which is why it was not suggested.
Ah, right, got it. I didn't think of that use case--- I think of lambda functions as on-the-fly things and that kind of polymorphism as something in a multipurpose library. I was writing a templated library that needs to accept user's lambda functions of any type and also provide defaults of the right type.
2

Another workaround for C++11 is by defining a template function and wrapping it within a lambda expression. However; this needs to define a new function for different templated lambdas:

struct ST{ int x; };

template<class T>
T templateFunc(T variable)
{
    return variable;
}

void func()
{
    ST st{10};
    auto lambda = [&](){return templateFunc<ST>(st);};
    auto res = lambda();
}

Comments

1

Here is one solution that involves wrapping the lamba in a structure:

template <typename T>                                                   
struct LamT                                                             
{                                                                       
   static void Go()                                                     
   {                                                                    
      auto lam = []()                                                   
      {                                                                 
         T var;                                                         
         std::cout << "lam, type = " << typeid(var).name() << std::endl;
      };                                                                

      lam();                                                            
   }                                                                    
};   

To use do:

LamT<int>::Go();  
LamT<char>::Go(); 
#This prints 
lam, type = i
lam, type = c

The main issue with this (besides the extra typing) you cannot embed this structure definition inside another method or you get (gcc 4.9)

error: a template declaration cannot appear at block scope

I also tried doing this:

template <typename T> using LamdaT = decltype(                          
   [](void)                                                          
   {                                                                 
       std::cout << "LambT type = " << typeid(T).name() << std::endl;  
   });

With the hope that I could use it like this:

LamdaT<int>();      
LamdaT<char>();

But I get the compiler error:

error: lambda-expression in unevaluated context

So this doesn't work ... but even if it did compile it would be of limited use because we would still have to put the "using LamdaT" at file scope (because it is a template) which sort of defeats the purpose of lambdas.

Comments

0

It's a bit verbose, but you can "unroll" a lambda into a callable object and use templates on the class definition. You can even capture variables, store the object into a variable as you would a lambda, or instantiate a new object for a single call. The possibilities are endless.

template <typename T>
struct Callable
{
    Callable(int& i) : capturedInt(i) {}
    T operator()(T a, T b)
    {
        T total = a;
        for (int i = 0; i < capturedInt; i++)
            total *= b;
        return total;
    }
    private:
        int& capturedInt;
};

int main() {
    int i = 5;
    Callable<float> callable(i);
    
    cout << "Result of callable(5)(10, 1.5f): " << callable(10, 1.5f) << '\n';

    i = 6;
    cout << "Result of callable(6)(1.5f, 10): " << callable(1.5f, 10) << '\n';

    i = 10;
    cout << "Result of Callable<int>(10)(2, 3): " << Callable<int>(i)(2, 3) << '\n';

    return 0;
}

Output:

Result of callable(5)(10, 1.5f): 75.9375
Result of callable(6)(1.5f, 10): 1.5e+06
Result of Callable<int>(10)(2, 3): 118098

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.