Доступ к типу возврата метода - PullRequest
1 голос
/ 20 марта 2019

Мне трудно заставить эту простую вещь работать.

Одна вещь, которую я нашел, которая работает:

#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 говорит

нестандартный синтаксис; используйте '&', чтобы создать указатель на член

Я могу поиграть с этим выражением все, что захочу, ничего хорошего из этого не выйдет.
e.g.:

using T = std::invoke_result_t< decltype(&A::Method) >;

ошибка: тип с именем 'type' отсутствует в 'std :: invoke_result

Если я удаляю decltype, это несоответствие значения типа (конечно) и т. Д ...

cppreference.com упоминает это использование для версии C ++ 14:

std::result_of<decltype(&C::Func)(C, char, int&)>::type

Не намного лучше, чем моя первая попытка. Все аргументы все еще там.
В действии в нашем простом случае: https://godbolt.org/z/KtQbth

Помощь?

Ответы [ 2 ]

2 голосов
/ 20 марта 2019

Вы можете использовать черту, предложенную Петр Скотницкий :

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>);
0 голосов
/ 20 марта 2019
[static_assert( std::is_same_v< decltype(std::declval<A>().Method()), int >);//super cool now][1]
...