39

查看有关折叠的 C++17论文(以及有关cppreference),我很困惑为什么选择仅与运算符一起使用?乍一看,似乎只需在 的元素之间插入(... + args)一个标记就可以更容易地扩展,但我不相信这是一个很好的决定。 +args

为什么二进制 lambda 表达式不能很好地工作并遵循与上述后者相同的扩展?在不支持任意可调用对象的情况下将折叠语法添加到语言中让我感到震惊,那么语法是否允许使用我只是没有看到的方法来使用它们?


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

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

2 回答 2

5

这是一篇很棒的论文和一个光荣的语言特性。如果我们绕过我不是特别喜欢的标准谈话,我想提出一个解决方法。由于我没有 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包装器类型中的类型已经提供了更多的扩展空间进入)。

于 2015-01-02T20:11:47.690 回答
5

首先,我很高兴我写的东西在 clang 中工作(我看到你的更新实现了我提到的 4 个步骤中的 3 个)。我必须感谢 Nick Athanasiou在写这篇文章之前与我讨论过的这种技术。

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

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

被排除在惰性评估和有状态操作符之外(或尚未包括在内,不能确定)。

于 2016-04-07T16:50:49.963 回答