cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
90 stars 0 forks source link

Использовать трюк определения std::function для conept с предикатами. #325

Closed apolukhin closed 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +2, -0 Автор идеи: d-yaroshev

Реализация для Predicate: https://godbolt.org/g/bSuuDb

Я бы таким образом записывал и StrictWeakOrder, Invocable итд - везде где речь идет про что-то, чему в качестве параметров передаются другие аргументы.

Мне кажется, так получается чище и понятнее, при этом пара скобок не увеличивает длину выражения.

apolukhin commented 3 years ago

yndx-antoshkka, 16 июля 2018, 11:27 Идея огонь! Скину авторам ranges TS.

yndx-antoshkka, 17 июля 2018, 15:33 Есть минусы в таком подходе - он не позволяет использовать сокращённый синтаксис https://godbolt.org/g/R3z5FF.

d-yaroshev, 18 июля 2018, 13:50 yndx-antoshkka, ой. А как terse syntax подставляет имя неявного параметра?

Andrey, 16 июля 2018, 16:17 Я чего-то не догнал в чем идея. Если вызвать

#include <array>

bool is_even(int);

void test(std::array<int, 3> xs) {
    my_find_if(xs.begin(), xs.end(), &is_even);
}

то в compute_is_predicate придет identity<Fn(int)>, где Fn = bool (*)(int). Что в этом хорошего?

d-yaroshev, 18 июля 2018, 13:42 Andrey, не очень вас понял. Есть concepts, идея concepts в том чтобы ограничивать шаблоны.

Вопрос в том что сейчас есть concept Predicate, например: https://en.cppreference.com/w/cpp/concepts/Predicate

И для find_if, нужно чтобы функтор, который ему передается, был Predicate.

Сейчас это предлагается писать как:

template <typename I, typename P>
  requires ForwardIterator<I> && Predicate<P, ValueType<I>>
I find_if(I f, I l, P p);

Мне кажется, что понятнее написать:

template <typename I, typename P>
  requires ForwardIterator<I> && Predicate<P(ValueType<I>)>
I find_if(I f, I l, P p);

Andrey, 19 июля 2018, 9:37 Ок, в первый раз я Вас не понял. То что Вы предлагаете (если я правильно понял сейчас) невозможно -- concept definition (в отличие от class template) нельзя частично специализировать.

d-yaroshev, 19 июля 2018, 9:46 Andrey, это абсолютно не страшно. Можете посмотреть на реализацию для Predicate из описания моего предложения.

d-yaroshev, 19 июля 2018, 11:56 Andrey, я что-то не понимаю( Какая разница как устроена шаблонная магия внутри стандартной библиотеки? Важно же какой интерфейс получает пользователь библиотеки, правда? Я могу не через identity сделать https://godbolt.org/g/Da2Ft5

Вас смушает, что тип параметра шаблона не осмысленный? Ну это некоторый DSL, я бы сказал, достаточно понятный.

Andrey, 19 июля 2018, 11:58 передавать как шаблонный аргумент identity? Да так можно. Но тогда я возвращаюсь к своему первому вопросу -- зачем это делать, если получающийся тип лишен смысл -- это function type, return type которого это function-like type, к примеру, функция принимающая int и возвращающая pointer на функцию принимающую int и возвращающую bool. Это все чтобы в месте использования Predicate писать Predicate<P(ValueType<I>)> вместо Predicate<P, ValueType<I>>, потому что первая конструкция кажется Вам понятнее. Но если вспомнить реальные подставляемые значения P и ValueType<I>, bool(*)(int) и int соответственно, то что же в этом естественного?

Andrey, 19 июля 2018, 12:00 d-yaroshev, ок, давайте сойдемся на том, что мне не нравится DSL в котором используются неосмысленные типы. Это вопрос вкуса, и спорить дальше смысла нет.

yndx-antoshkka, 19 июля 2018, 18:14 Мне подсказали, что комитет рассматривал и отказался от этой идеи. "Она ведёт к нерприятным сюрпризам из-за decay типов аргументов функции при формированиии типа функции."