原文链接:c++11标准 decltype,result_of和后置返回类型
c++11提供了decltype和result_of两种类型推导方法.
decltype用于表达式类型推导
result_of用于函数或可调用对象,例如function,函数指针
decltype
decltype是在编译时获取表达式或对象的返回值类型,适用于泛型编程类型的获取
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| int a=0; decltype(a) b=1;
int f(){ std::cout<<"f()\n"; return 0; } decltype(f()) c=2;
template<typename T,typename U> auto gf(T t,U u)->decltype(t+u){ return t+u; } std::cout<<gf(1,2)<<"\n"; std::cout<<gf(1.1,2.1)<<"\n";
函数有参时就不建议使用decltype获取返回类型了,因为一般需要构造一个实例作为参数 如 decltype(f(float())) c=1; 但有些对象可能无法构造如抽象类
|
std::declval: 对于表达式的参数 不构造实例 获取返回类型
如果希望表示一个类的成员函数的返回值类型,但是不能创造这个实例时,可以通过declval创建一个类的引用获取成员函数返回值
同样适用于抽象类无法构造实例
1 2 3 4 5 6 7
| class A{ public: int f(){ return 0; } }; decltype(std::declval<A>().f()) d=3;
|
result_of
result_of(c++11),result_of_t(c++14),invoke_result(c++17)
result_of在不同标准中多次修改,如果没有限定c++标准的化,应使用invoke_result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template <typename F, typename... Args> class result_of<F(Args...)>;
template< class F, class... ArgTypes > class invoke_result; F为调用对象,Args为参数类型
int f(float a){ std::cout<<"f()\n"; return 0; } std::result_of<decltype(&f)(float)>::type a=1; std::invoke_result<decltype(f), float>::type a=1;
|
实例:分析线程池任务入队的函数返回类型
1 2
| template<typename F> auto enque(F&& f)->std::future<typename std::result_of<F()>::type>;
|
该函数使用一个后置返回类型
F一般是一个函数或可调用对象function,并且是无参封装的,因此std::result_of<F()>::type就是函数的返回值.
typename是用于在这些模板传参中,有类型传参的函数中,如果使用result_of,那需要typename声明这个result_of::type是一个类型
因此该函数就是 将function f构造一个task,入队,并将该task的返回值传给future,作为返回值.