1.1.函数:
std::result_of (removed in C++20)
template< class F, class... ArgTypes> (since C++17)
class invoke_result;
template< class F, class... ArgTypes> -2 (since C++17)
using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
1.2.用途:
推导在编译时INVOKE表达式的返回类型
1.3.说明:
类F任何完整类型ArgTypes,未知范围数组或(可能是cv限定)void
为此页面上描述的任何模板添加专门化的程序的行为是未定义的
1.4.注意:
1)F(Args...)以Args.为参数类型,F返回类型
2)F 不能是函数类型或数组类型(但可以是对它们的引用)
3)如果任何一Args具有“数组T”类型或函数类型T,它会自动调整为T*;
4)无论是F还是任何Args.都不能是抽象类类型
5)如果Args中的任何一个参数有一顶级cv-限定符会被丢弃;
6)没有一个Args参数是void
//为避免这些怪癖,result_of通常将引用类型与F和一起使用Args...
template<class F, class... Args>
std::result_of_t<F&&(Args&&...)> // 替代result_of_t<F(Args...)>, 错误
my_invoke(F&& f, Args&&... args) {...}
2.实例:
#include <assert.h>
#include <type_traits>
#include <iostream>
using namespace std;
struct A {
double operator()(char, int&) {}
float operator()(int) { return 1.0; }
};
int func(const int& x){ return x;}
struct CallObject {
inline CallObject(const int& val) {}
template<typename T>
inline T operator()(const T& x)noexcept{return x;}
};
struct CObject {
int data;
inline CObject(const int& val) :data(val) {}
inline int getData(const int& x)noexcept{return data+x;}
};
template<class T>
typename std::result_of<T(int)>::type f(T& t)
{
std::cout << "overload of f for callable T\n";
return t(0);
}
template<class T, class U>
int f(U u)
{
std::cout << "overload of f for non-callable T\n";
return u;
}
int main() {
//普通函数:
static_assert(is_same<int(const int&), decltype(func)>::value, ""); //注意func并没有转为指针
static_assert(is_same<int(*)(const int&), decltype(&func)>::value, "");
static_assert(is_same<int(&)(const int&), decltype(func)&>::value, "");
static_assert((is_same<int(*)(const int&), //注意func转为指针
invoke_result<decltype(&func)(const int&), const int&>::type>::value) == true);
cout << typeid(invoke_result<decltype(func), const int&>::type).name() << endl; //int
cout << typeid(invoke_result<decltype(func)&, const int&>::type).name() << endl;//int
cout << typeid(invoke_result<decltype(&func), const int&>::type).name() << endl;//int
cout << typeid(invoke_result<decltype(func)*, const int&>::type).name() << endl; //int
cout << typeid(invoke_result<decltype(func)&(const int&), const int&>::type).name() << endl;//int __cdecl(int const & __ptr64)
cout << typeid(invoke_result<decltype(func)*(const int&), const int&>::type).name() << endl; //int __cdecl(int const & __ptr64)
cout << typeid(invoke_result<CallObject, const int&>::type).name() << endl;//int
cout << typeid(invoke_result<CallObject, float>::type).name() << endl;//float
//decltype(declval<CObject>().getData(declval<const int&>()));//错误?不明白请高手补充
cout << is_same<int, decltype(declval<CObject>().data)>::value << endl;
cout << typeid(invoke_result<decltype(&CObject::getData), CObject, const int&>::type).name() << endl;//int
//用char和int&参数调用A的结果是double
std::result_of<A(char, int&)>::type x1 = 3.14; // double x1;
static_assert(std::is_same<decltype(x1), double>::value, "");
// std :: invoke_result使用不同的语法(不带括号)
std::invoke_result<A, char, int&>::type x2 = 3.14;// double x1;
static_assert(std::is_same<decltype(x2), double>::value, "");
//用int参数调用A的结果是float
std::result_of<A(int)>::type x3 = float(3.14); // float x3;
static_assert(std::is_same<decltype(x3), float>::value, "");
std::invoke_result<A, int>::type x31 = float(3.14);// float x1;
static_assert(std::is_same<decltype(x31), float>::value, "");
// result_of可以与指向成员函数的指针一起使用,如下所示:
struct B { double Func(char, int&); };
std::result_of<decltype(&B::Func)(B, char, int&)>::type x4 = 3.14;
static_assert(std::is_same<decltype(x4), double>::value, "");
cout << typeid(invoke_result<decltype(&B::Func), B, char, int&>::type).name() << endl;//double
// B++11错误; calls the non-callable overload in B++14
f<B>(1);// 输出overload of f for non-callable T
}