Что такое замена для std :: function :: argument_type?

Согласно cppreference.com, все три следующих argument_type: argument_type, first_argument_type и second_argument_type устарели на С++ 17 и удалены в С++ 20.

Какова стандартная замена библиотеки для этих типов участников? Я имею в виду, что я мог бы писать свои собственные черты характера, но я сомневаюсь, что что-то удаляется без надлежащей замены в стандартной библиотеке.

В качестве примера:

template <typename F> 
void call_with_user_input(F f) {
    typename F::first_argument_type x;  // what to use instead ??
    std::cin >> x;
    f(x);
}

Ответ 1

Вы можете получить тип, введя параметры шаблона

template <typename Ret, typename Arg> 
void call_with_user_input(std::function<Ret(Arg)> f) {
    Arg x;
    std::cin >> x;
    f(x);
}

Дает вам тип аргумента в качестве параметра шаблона. В качестве бонуса вы также получите тип возврата, если вам это нужно.

Ответ 2

По моему мнению, они будут удалены и что это будет. Я нашел это предложение здесь.

Связано с first_argument_type и second_argument_type:

Адаптируемые привязки функций были сильным кандидатом на удаление в С++ 17, но были сохранены только потому, что не было адекватной замены для пользователей унарных/двоичных отрицателей для миграции. Эта функция, std :: not_fn, была добавлена в С++ 17, чтобы разрешить путь миграции,

Проверка std :: not_fn для С++ 17 я обнаружил, что:

Обратите внимание, что протокол адаптивной функции больше не функционирует, когда он был изначально разработан, благодаря добавлению новых языковых функций и библиотек, таких как лямбда-выражения, функторы "алмаза" и т.д. Это происходит не из-за отсутствия усилий, а просто для того, чтобы не было уникального набора typedef для некоторых из этих типов, таких как полиморфные лямбда-объекты. Тем не менее, мы платим за сохранение поддержки в другом месте в библиотеке из-за неудобных условно определенных членов typedefs в нескольких компонентах, таких как std :: function, обертывающих тип функции с точно одним или двумя параметрами или аналогично для std :: reference_wrapper для ссылок на функции одного или двух аргументов.

Это означает, что их просто удалит.

Одна из проблем с параметрами first_argument_type и second_argument_type видимому, second_argument_type с polymorphic lambda objects.

Также, как указано в комментариях, все, что имеет несколько operator() которые могут быть переданы в std::variant<...>::visit имеет проблему с first_argument_type

Ответ 3

Один из способов - использовать boost::function_types:

#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/at.hpp>

template <typename F> 
void call_with_user_input(F f) {
    using FnType = decltype(&F::operator());
    using FirstArgType = typename boost::mpl::at_c<boost::function_types::parameter_types<FnType>, 0>::type;
    FirstArgType x;
    std::cin >> x;
    f(x);
}