访问 return 类型的方法
Accessing the return type of a method
我很难让这个简单的事情继续下去。
我发现了一件有用的事情:
#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
>
);
不。
call to non-static member function without an object argument
MSVC 说
non-standard syntax; use '&' to create a pointer to member
我可以fiddle用这个表达我想要的一切,没有什么好处。
例如:
using T = std::invoke_result_t< decltype(&A::Method) >;
error: no type named 'type' in 'std::invoke_result
如果我删除 decltype
它的类型值不匹配(当然)等等...
cppreference.com 提到了 C++14 版本的这种用法:
std::result_of<decltype(&C::Func)(C, char, int&)>::type
并不比我的第一次尝试好多少。所有的争论都还在。
在我们的简单案例中的实际操作:https://godbolt.org/z/KtQbth
求助?
您可以使用Piotr Skotnicki建议的特征:
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]
我很难让这个简单的事情继续下去。
我发现了一件有用的事情:
#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
>
);
不。
call to non-static member function without an object argument
MSVC 说
non-standard syntax; use '&' to create a pointer to member
我可以fiddle用这个表达我想要的一切,没有什么好处。
例如:
using T = std::invoke_result_t< decltype(&A::Method) >;
error: no type named 'type' in 'std::invoke_result
如果我删除 decltype
它的类型值不匹配(当然)等等...
cppreference.com 提到了 C++14 版本的这种用法:
std::result_of<decltype(&C::Func)(C, char, int&)>::type
并不比我的第一次尝试好多少。所有的争论都还在。
在我们的简单案例中的实际操作:https://godbolt.org/z/KtQbth
求助?
您可以使用Piotr Skotnicki建议的特征:
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]