用任意可调用的折叠表达式?

时间:2014-12-20 18:01:02

标签: c++ fold c++17

在折叠上查看C ++ 17 paper(和cppreference),我很困惑为什么选择只与运营商合作?乍一看似乎只是通过在(... + args)的元素之间推一个+标记来扩展args更容易,但我不相信这是一个伟大的决定。

为什么二进制lambda表达式不能同样工作并遵循与上面相同的扩展?对我来说,在不支持任意可调用语言的情况下将折叠语法添加到语言中是很不可思议的,那么语法是否允许使用我没有看到的方法?


更新:这适用于具有clang的可变参数min()

template <typename T>
struct MinWrapper {
    const T& obj;
};

template <typename T, typename U, typename V=std::common_type_t<T,U>>
constexpr MinWrapper<V> operator%(
        const MinWrapper<T>& lhs, const MinWrapper<U>& rhs) {
    return {lhs.obj < rhs.obj ? lhs.obj : rhs.obj};
}


template <typename... Ts>
constexpr auto min(Ts&&... args) {
    return (MinWrapper<Ts>{args} % ...).obj;
}

2 个答案:

答案 0 :(得分:4)

这是一篇很棒的论文和一个光荣的语言特色。如果我们绕过了我并不特别喜欢的标准话题,我想提出一个解决方法。由于我没有c ++ 17编译器(或时间机器),我的答案只是概述,我相信可能是一个解决方案,提供带有任意函数的折叠表达式语言状态。

1。定义一个类型包装器(一个轻量级的包装器)

template<typename T>
struct wp {
    T const& val; 
    // yes there should be constructors
};

2。将包装转换为包装包装的机器

template<typename Op, typename Ts...>
using wrapped_pack = make_wrapped<Op, Ts..>

3。重载wp<T>

的内置运算符
template<typename T, typename U>
ret_val operator+(wp<T> const& lhs, wp<U> const& rhs) {...}

4。在折叠表达式

中使用包装的包

这需要一个额外的层,其中折叠的args被转换为包装的参数


上述明显的缺点是它不能保证唯一性(或可伸缩性):使用自定义函子的每个折叠都会消耗内置的运算符重载。

应根据他们遇到的表达方式改变类型,但我不想深入思考实验(例如使用Op的类型包装器的类型已经提供了更大的空间来扩展。

答案 1 :(得分:3)

首先,我很高兴我写的内容在clang中起作用(我看到你的更新实现了我提到的4个步骤中的3个)。我必须赞扬 Nick Athanasiou这项技术,在编写this之前与我讨论这个问题。

我现在提到这个的原因是因为我被告知他发布了一个实现这个东西的library(在升级库incubator中);您可以找到相关文档here 。这似乎是最初的想法(我们都在这里使用)并允许这样的代码:

(Op<Max>(args) + ...); // Op is a function producing the custom fold type

被排除在外,倾向于懒惰的评估和有状态的运营商(或者尚未包括在内,无法确定)。