Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template specialization for passing a lambda

I am stuck on specializing a template function for a lambda :

class X
{
  public:
    template <typename T>
    void f(T t) 
    { 
      std::cout << "awesome" << std::endl; 
    };

    template <>
    void f(double t) 
    {
      std::cout << "trouble" << std::endl; // Works
    }

    template <>
    void f(??? t) // what to put here?
    {
      std::cout << "lambda" << std::endl;
    }  
};


X x;
x.f(42); // prints "awesome"
x.f(1.12); // prints "trouble"
x.f([](){ std::cout << "my lazy lambda" << std::endl; }); // should print "lambda"

Casting the lambda to a std::function before passing to f and specializing for this type works, but is tedious to write. Is there a solution in C++0x?

Edit: I am totally fine with a solution, which would enable me to specialize for a callable if the last line of passing a lambda works.

like image 875
Christopher Oezbek Avatar asked May 01 '26 17:05

Christopher Oezbek


1 Answers

The following is a variation of the good old sizeof trick. Maybe it can be done with decltype alone. It does not exactly check if its a lambda, but if it is callable. If you want to filter out other callable things, you can use C++0x type traits to check if they are functions, member functions, composit objects etc.

#include <functional>
#include <iostream>
#include <type_traits>

template<class T>
char is_callable( const T& t, decltype( t())* = 0 );

long is_callable( ... );

class X
{
  public:
    template <typename T>
    void f( const T& t, typename std::enable_if<sizeof(is_callable(t)) !=1>::type* = 0 )
    {
      std::cout << "awesome" << std::endl;
    };

    void f(double )
    {
      std::cout << "trouble" << std::endl; // Works
    }

    template<class T>
    void f( const T& t, typename std::enable_if<sizeof(is_callable(t)) == 1>::type* = 0 )
    {
      std::cout << "lambda" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    X x;
    x.f(42); // prints "awesome"
    x.f(1.12); // prints "trouble"
    x.f([](){ std::cout << "my lazy lambda" << std::endl; }); // should print "lambda"
}
like image 123
PlasmaHH Avatar answered May 04 '26 08:05

PlasmaHH



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!