Доступ к типу возврата метода
Я с трудом справляюсь с этой простой вещью.
Я нашел одну вещь, которая работает:
#include <type_traits>
struct A
{
int Method();
};
static_assert( std::is_same_v<
decltype(A{}.Method()), int
>
); // pass. cool.
Ок, отлично. Но нет; не хорошо. Поскольку теперь у меня есть требование по умолчанию, и мне нужно написать выражение вызова со всеми аргументами. И кто о них знает!
Рассмотрим реальную ситуацию:
struct A
{
int Method(MysteriousArgumentsIDontCareAboutAndCanChangeInTheFuture);
};
static_assert( std::is_same_v<
decltype(A{}.Method()), int
>
); // not so cool anymore (too few arguments to function call, expected 1, have 0)
Как насчет использования std::invoke_result
?
static_assert( std::is_same_v<
std::invoke_result_t< A::Method >, int
>
);
Неа.
вызов нестатической функции-члена без аргумента объекта
MSVC говорит
нестандартный синтаксис; используйте '&', чтобы создать указатель на член
С этим выражением я могу играть все, что захочу, ничего хорошего из этого не выйдет.
например:
using T = std::invoke_result_t< decltype(&A::Method) >;
ошибка: нет типа с именем 'тип' в 'std::invoke_result
Если я удалю decltype
это несоответствие значения типа (конечно) и т.д...
cppreference.com упоминает это использование для версии C++14:
std::result_of<decltype(&C::Func)(C, char, int&)>::type
Не намного лучше, чем моя первая попытка. Все аргументы все еще там.
В действии в нашем простом случае: https://godbolt.org/z/KtQbth
Помогите?
2 ответа
Вы можете использовать черту, предложенную Петром Скотницким:
template <typename T>
struct return_type;
template <typename R, typename... Args>
struct return_type<R(Args...)> { using type = R; };
template <typename R, typename... Args>
struct return_type<R(*)(Args...)> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...)> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) &> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) &&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) volatile&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const volatile&&> { using type = R; };
template <typename T>
using return_type_t = typename return_type<T>::type;
Теперь вы можете сделать:
static_assert(std::is_same_v<return_type_t<decltype(&A::Method)>, int>);
[static_assert( std::is_same_v< decltype(std::declval<A>().Method()), int >);//super cool now][1]