0%

原文链接: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
//1 变量类型
int a=0;
decltype(a) b=1;

//2 表达式类型
int f(){
std::cout<<"f()\n"; //不会输出
return 0;
}
decltype(f()) c=2; //decltype不会执行函数


//3 作为函数的后置返回类型
template<typename T,typename U>
auto gf(T t,U u)->decltype(t+u){
return t+u;
}
std::cout<<gf(1,2)<<"\n"; //3
std::cout<<gf(1.1,2.1)<<"\n"; //3.2

// 4 有参函数表达式类型
函数有参时就不建议使用decltype获取返回类型了,因为一般需要构造一个实例作为参数
decltype(f(float())) c=1; 但有些对象可能无法构造如抽象类

std::declval: 对于表达式的参数 不构造实例 获取返回类型

如果希望表示一个类的成员函数的返回值类型,但是不能创造这个实例时,可以通过declval创建一个类的引用获取成员函数返回值

同样适用于抽象类无法构造实例

1
2
3
4
5
6
7
class A{
public:
int f(){ //或者抽象类virtual int f(){
return 0;
}
};
decltype(std::declval<A>().f()) d=3; //std::declval<A>()是一个引用

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
// result_of
template <typename F, typename... Args>
class result_of<F(Args...)>;

// invoke_result
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; //c++11
std::invoke_result<decltype(f), float>::type a=1; //c++17以上

实例:分析线程池任务入队的函数返回类型

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,作为返回值.