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

Rya*_*ing 35 c++ fold c++17

回顾关于折叠的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;
}
Run Code Online (Sandbox Code Playgroud)

Lor*_*ins 5

那是一篇很棒的论文,也是一个很棒的语言功能。如果我们绕过我不是特别喜欢的标准谈话,我想提出一个解决方法。由于我没有 c++17 编译器(或时间机器),我的答案只会概述,我认为可能是,提供具有语言状态的任意函数的折叠表达式的解决方案。

1. 定义类型包装器(轻量级包装器)

template<typename T>
struct wp {
    T const& val; 
    // yes there should be constructors
};
Run Code Online (Sandbox Code Playgroud)

2. 将包装转变为包装包装的机械

template<typename Op, typename Ts...>
using wrapped_pack = make_wrapped<Op, Ts..>
Run Code Online (Sandbox Code Playgroud)

3. 重载一个内置操作符 wp<T>

template<typename T, typename U>
ret_val operator+(wp<T> const& lhs, wp<U> const& rhs) {...}
Run Code Online (Sandbox Code Playgroud)

4.在折叠表达式中使用wrapped pack

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


上述的一个明显缺点是它不保证唯一性(或可扩展性):带有自定义可调用的每个折叠都会消耗内置的运算符重载。

应该有一些技巧可以根据它们遇到的表达式来改变类型,但我不想深入研究思想实验(例如Op,在包装器的类型中使用类型已经提供了更多的扩展空间进入)。


Lor*_*ins 5

首先,我很高兴我写的东西在 clang 中有效(我看到你的更新实现了我提到的 4 个步骤中的 3 个)。我必须给予信贷 尼克Athanasiou这个技术,这样在写之前同我讨论过这

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

(Op<Max>(args) + ...); // Op is a function producing the custom fold type
Run Code Online (Sandbox Code Playgroud)

被排除在外,取而代之的是惰性求值和有状态运算符(或尚未包括在内,无法确定)。