Подтвердить что ты не робот

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

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

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


Обновление: Это работает для вариационной функции 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;
}
4b9b3361

Ответ 1

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

Для этого потребуется дополнительный слой, где args складки преобразуются в завернутые аргументы


Очевидным недостатком вышесказанного является то, что он не гарантирует уникальность (или масштабируемость): каждая сводка с пользовательским функтором будет потреблять встроенную перегрузку оператора.

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

Ответ 2

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

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

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

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