В чем причина того, что `std::result_of` устарела в C++17?

Я видел std::result_of осуждается в C++17.

  • В чем причина std::result_of устарел в C++17?
  • Также я хотел бы знать разницу между std::result_of а также std::invoke_result,

4 ответа

ТС уже предоставил очевидную ссылку, но, пожалуй, самая ужасная причина повторяется: result_of участвует в формировании типа F(Arg1, Arg2, ...) не для функции, возвращающей эти типыF но для функции типа F принимая эти типы. (В конце концов, тип возврата является результатом, ну, result_of, а не вход!)

@haelix:

Я полностью согласен с вами по поводу отсутствия примера на странице cppreference. Вот мое мнение:

auto add_auto_fn(int a, int b) {
    return a + b;
}

template<typename U, typename V>
auto add_auto_template_fn(U a, V b) {
    return a + b;
}

int fortytwo(int a, int b) { return a + 42; }

struct my_functor{
    auto operator() (int a) { return a + 42; }
};

void test_invoke_result()
{
    {
        // For functions and auto function: use < decltype(&f), Args... >
        using T = std::invoke_result< decltype(&fortytwo), int, int>::type;
        static_assert(std::is_same<T, int>::value, "");
    }
    {
        // For templated auto functions: use < decltype(&f)<Args...>, Args... >
        using T = std::invoke_result< decltype(&add_auto_template_fn<int, double>), int, double>::type;
        static_assert(std::is_same<T, double>::value, "");
    }
    {
        // For simple lambdas: use < decltype(lambda), Args... >
        auto simple_lambda = [](int a) {  return a + 42; };
        using T = std::invoke_result< decltype(simple_lambda), int>::type;
        static_assert(std::is_same<T, int>::value, "");
    }
    {
        // For generic lambdas: use < decltype(lambda), Args... >
        auto generic_lambda = [](auto a) {  return a + 42; };
        using T = std::invoke_result< decltype(generic_lambda), double>::type;
        static_assert(std::is_same<T, double>::value, "");
    }
    {
        // For functors: use < functor, Args... >
        using T = std::invoke_result< my_functor, int>::type;
        static_assert(std::is_same<T, int>::value, "");
    }

}

void test_result_of()
{
    {
        // For functions and auto function: use < decltype(&f)(Args...) >
        using T = std::result_of< decltype(&fortytwo)(int, int)>::type;
        static_assert(std::is_same<T, int>::value, "");
    }
    {
        // For templated auto functions: use < decltype(&f<Args...>)(Args...) >
        using T = std::result_of< decltype(&add_auto_template_fn<int, double>)(int, double)>::type;
        static_assert(std::is_same<T, double>::value, "");
    }
    {
        // For simple lambdas: use < decltype(lambda)(Args...) >
        auto simple_lambda = [](int a) {  return a + 42; };
        using T = std::result_of< decltype(simple_lambda)(int)>::type;
        static_assert(std::is_same<T, int>::value, "");
    }
    {
        // For generic lambdas: use < decltype(lambda)(Args...) >
        auto generic_lambda = [](auto a) {  return a + 42; };
        using T = std::result_of< decltype(generic_lambda)(double)>::type;
        static_assert(std::is_same<T, double>::value, "");
    }
    {
        // For functors: use < functor(Args...) >
        using T = std::result_of< my_functor(int)>::type;
        static_assert(std::is_same<T, int>::value, "");
    }

}

Чтобы использовать его, вам нужно изменить с

      std::result_of_t<A(B)> 

к

      std::invoke_result_t<A, B>

или в шаблоне

      std::result_of_t<F(Args...)>

к

      std::invoke_result_t<F,Args...>

Это очень хорошо объяснено на cppreference :

F(Args...)— это тип функции, который является типом аргумента и типом возвращаемого значения.
Как таковой,std::result_ofстрадает от нескольких причуд, которые привели к его устареванию в пользуstd::invoke_resultв С++17:

  • не может быть типом функции или типом массива (но может быть ссылкой на них);
  • если какой-либо изArgsимеет тип "массив" или тип функцииT, он автоматически настраивается наT*;
  • ни одинFни один из них не может быть типом абстрактного класса;
  • если какой-либо из них имеет классификатор cv верхнего уровня, он отбрасывается;
  • ни один изArgs...может быть типаvoid.
Другие вопросы по тегам