Сложите выражения с произвольным вызовом?

Оглядываясь на C ++ 17 бумага на складках, (и на cppreference), Я запутался, почему был сделан выбор работать только с операторами? На первый взгляд кажется, что было бы легче расширить (... + args) просто пихая + знак между элементами argsНо я не уверен, что это отличное решение.

Почему бинарное лямбда-выражение не может работать так же хорошо и следовать тому же расширению, что и последнее выше? Меня раздражает, что синтаксис сгиба будет добавлен к языку без поддержки произвольных вызываемых элементов, поэтому синтаксис позволяет использовать их, чего я просто не вижу?


Обновить: Это работает для вариада 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;
}

33

Решение

Это отличная статья и замечательная языковая особенность. Если мы обойдем стандартный разговор, который мне не особо нравится, я бы хотел предложить обходной путь. Поскольку у меня нет компилятора 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 в типе обертки уже дает гораздо больше места для масштабирования в).

4

Другие решения

Прежде всего, я рад, что написанное мной работает в clang (я вижу, что ваше обновление реализует 3 из 4 шагов, которые я упомянул). Мне пришлось отдать должное Ник Атанасиу для этой техники, которая обсуждала это со мной, прежде чем писать этот.

Причина, по которой я упоминаю об этом сейчас, заключается в том, что мне сообщили, что он выпустил библиотека (в буст-библиотеке инкубатор) который реализует этот материал; ты можешь найти сопутствующая документация Вот. Кажется, первоначальная идея (которую мы оба здесь используем) и допустимый код:

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

был оставлен в пользу ленивых вычислений и операторов с сохранением состояния (или еще не включен, не может знать наверняка).

2