Оглядываясь на 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;
}
Это отличная статья и замечательная языковая особенность. Если мы обойдем стандартный разговор, который мне не особо нравится, я бы хотел предложить обходной путь. Поскольку у меня нет компилятора c ++ 17 (или машины времени), мой ответ будет лишь наметить, как мне кажется, решение для обеспечения складывать выражения с произвольными функциями со статусом языка как есть.
template<typename T>
struct wp {
T const& val;
// yes there should be constructors
};
template<typename Op, typename Ts...>
using wrapped_pack = make_wrapped<Op, Ts..>
wp<T>
template<typename T, typename U>
ret_val operator+(wp<T> const& lhs, wp<U> const& rhs) {...}
Это потребует дополнительного слоя, где args
сгиба превращаются в завернутые аргументы
Очевидным недостатком вышесказанного является то, что он не гарантирует уникальность (или масштабируемость): каждый фолд с пользовательским функтором потребляет встроенную перегрузку оператора.
Должны быть хаки, чтобы варьировать типы в зависимости от выражения, с которым они встречаются, но я не хочу погружаться так глубоко в мысленный эксперимент (например, используя тип Op
в типе обертки уже дает гораздо больше места для масштабирования в).
Прежде всего, я рад, что написанное мной работает в clang (я вижу, что ваше обновление реализует 3 из 4 шагов, которые я упомянул). Мне пришлось отдать должное Ник Атанасиу для этой техники, которая обсуждала это со мной, прежде чем писать этот.
Причина, по которой я упоминаю об этом сейчас, заключается в том, что мне сообщили, что он выпустил библиотека (в буст-библиотеке инкубатор) который реализует этот материал; ты можешь найти сопутствующая документация Вот. Кажется, первоначальная идея (которую мы оба здесь используем) и допустимый код:
(Op<Max>(args) + ...); // Op is a function producing the custom fold type
был оставлен в пользу ленивых вычислений и операторов с сохранением состояния (или еще не включен, не может знать наверняка).