C++专门为某种类型使用lambda

dav*_*igh 9 c++ lambda template-specialization c++14

我正在玩这里提到的lambda"overloading" ,很快就发现我可以很方便地创建专门的lambda闭包.所以我最初是试错了,我最有希望的试验是

auto call_for_vector = [] template<typename T> (std::vector<T>) {};
Run Code Online (Sandbox Code Playgroud)

然而,稍后对cppreference的看法表明,标准似乎不允许使用这种结构或类似结构.

为什么不支持此类专业化的原因是什么?

我知道可以使用SFINAE获得这种行为,但是它的可读性更低,更难写,更容易出错.当然也可以用适当的方式编写一个类operator(),但这是洙C++ 03 :-)



这种语法会有什么用处?:

一个例子,这将允许像下面的代码中那样容易的lambda"重载"

template <class F1, class F2>
struct overload_set : F1, F2
{
    overload_set(F1 x1, F2 x2) : F1(x1), F2(x2) {}
    using F1::operator();
    using F2::operator();
};

template <class F1, class F2>
overload_set<F1,F2> overload(F1 x1, F2 x2)
{
    return overload_set<F1,F2>(x1,x2);
} 

auto f = overload(
         [](auto&& x){ std::cout<<"call by default"<<std::endl;},
         [] template<typename T>(std::vector<T>){std::cout<<"call for vector"<<std::endl;}
         );
Run Code Online (Sandbox Code Playgroud)

人们可以获得这种行为,例如通过使用SFINAE基于该答案中的技术,但是再次......这很糟糕.

SFINAE是否有一个简单的解决方法来获得特定的过载?

Nik*_*iou 2

这种类型的编码乍一看似乎是多余的,但我们可以利用一些很好的属性。关于您提到的帖子,我正在计划第 2 部分,其中我将展示一种检查类型是否具有特定成员(函数或数据)的巧妙方法。假设您要检查serialize成员函数;我发现它变得简单,而不是使用复杂的机制:

auto hs = overload( 
    [ ](auto&& x) -> decltype(x.serialize(2), std::true_type{}) { 
        return{}; },       // ^^ this guy ^^ 
    [ ](...) -> std::false_type { return {}; }); 
Run Code Online (Sandbox Code Playgroud)

demo

标准演化的细节可以在这里找到,但我发布这篇文章的原因是为了提倡这样一种语法,如果我们已经有了它,上面的内容可以扩展允许“重载”通用 lambda之间的部分排序

auto do_something = overload( 
    [ ]<class X>(shared_ptr<X> x) -> decltype(x.serialize(2), std::true_type{}) { 
        /*do something specific for shared ptrs of X */ return{}; },      
    [ ]<class X>(X& x) -> decltype(x.serialize(2), std::true_type{}) { 
        /*do a generic operation for other types that have serialize*/return{}; },      
    [ ](...) -> std::false_type { /*do nothing*/ return {}; }); 
Run Code Online (Sandbox Code Playgroud)

  • 啊,是的,所以sfinae,但是现代(和更短)的方式...... (2认同)