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

时间:2016-02-14 15:36:27

标签: c++ lambda c++14 template-specialization

我正在玩lambda"重载"正如here所示,并且我很快就发现了创建专门的lambda闭包很方便的地步。所以我第一次试错了,我最有希望的试验是

auto call_for_vector = [] template<typename T> (std::vector<T>) {};

然而,稍后查看cppreference表明标准似乎不允许使用此类构造。

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

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

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

一个例子,这将允许一个简单的lambda&#34;过载&#34;如下面的代码

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;}
         );

可以获得此行为,例如通过使用SFINAE基于this answer中的技术,但再次......这很糟糕。

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

1 个答案:

答案 0 :(得分:2)

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

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

demo

可以找到标准进化的具体细节here,但我发布这个的原因是为了提倡这样的语法,如果我们已经拥有它,上面的内容可以扩展 允许&#34;重载&#34; 通用lambdas 之间的部分排序:

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 {}; });