Templates 传递lambda的模板专门化

Templates 传递lambda的模板专门化,templates,lambda,c++11,template-specialization,Templates,Lambda,C++11,Template Specialization,我一直专注于专门化lambda的模板函数: class X { public: template <typename T> void f(T t) { std::cout << "awesome" << std::endl; }; template <> void f(double t) { std::cout << "trouble" <

我一直专注于专门化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"
X类
{
公众:
模板
空隙f(T)
{ 

std::cout您不能直接这样做:lambda的类型是由编译器创建的,对于每个lambda都是不同的。您可以对它进行专门化,但它只能用于该类型(请参见下面的示例)。您可以通过使用一个小函数来转换lambda->std::function来消除一些繁琐的操作

auto myLambda = [](){ std::cout << "myLambda" << std::endl; };

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

    void f( const std::function< void() >& f )
    {
      std::cout << "function" << std::endl;
    }

    void f( const decltype( myLambda )& f )
    {
      std::cout << "myLambda" << std::endl;
    }
};

  //helper for lambda -> function
template< class T >
std::function< void() > Function( const T& f )
{
  return std::function< void() >( f );
}

X x;
x.f( myLambda ); //prints "myLambda"
x.f( Function( [](){ std::cout << "blah" << std::endl; } ) ); //prints "function"
x.f( [](){ std::cout << "blah" << std::endl; } ); //still won't work: not the same type as myLambda!

auto myLambda=[](){std::cout以下是旧的sizeof技巧的一个变体。也许可以单独使用decltype来完成。它并不确切地检查它是否是lambda,但它是否可调用。如果你想过滤掉其他可调用的东西,你可以使用C++0x类型特征来检查它们是否是函数、成员函数、复合对象等

#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"
}
#包括
#包括
#包括
模板
char是可调用的(const T&T,decltype(T())*=0);
long是可调用的(…);
X类
{
公众:
模板
空f(常数T&T,类型名称std::enable_如果::类型*=0)
{

std::cout-related:因此答案似乎是:不,在C++0x中没有办法避免强制转换并专门化一个模板来匹配lambdas,不可能将lambda函数与其他不专门用于lambda的可调用对象区分开来,只有可调用类型-不是同一件事。这可能是最好的方法,可能只是更改sfinae以测试确切的签名,而不是所有可调用的types@DeadMG:我完全可以匹配任何可调用项,只要我可以避免最后一行永远不会匹配lambda,因为每个lambda都有不同的唯一类型