我被玩弄的拉姆达“超载”所呈现在这里,并且很快就在那里我发现它方便地创建专业拉姆达倒闭的地步。所以我有点初试,最有希望的尝试是
auto call_for_vector = [] template<typename T> (std::vector<T>) {};
但是,稍后查看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;}
);
例如,可以通过基于此答案中的技术使用SFINAE来获得这种行为,但这又很糟糕。
SFINAE是否有一种简单的解决方法来获取特定的过载?
这类编码乍看起来似乎是多余的,但是我们可以利用一些不错的属性。关于您提到的帖子,我正在计划第2部分,其中展示了一种检查类型是否具有特定成员(函数或数据)的巧妙方法。假设您要检查serialize
成员函数;而不是使用复杂的机制,我发现它变得很简单:
auto hs = overload(
[ ](auto&& x) -> decltype(x.serialize(2), std::true_type{}) {
return{}; }, // ^^ this guy ^^
[ ](...) -> std::false_type { return {}; });
可以在此处找到标准演变的细节,但是我发布此消息的原因是倡导使用这样一种语法,如果已经有了它,则可以扩展以上内容以允许“重载”通用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 {}; });
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句