1.1.定义:
template<class T>
typename std::add_rvalue_reference<T>::type declval() noexcept; (since C++11)
1.2.用途:
将任何类型转为引用类型,从而可用在decltype表达式而无需通过构造函数
1.3.说明:
1)declval通常在模板中使用;模板参数可能没有构造函数,但具有返回类型的函数
2)不管是否有没有默认构造函数或该类型不可以创建对象。(可以用于抽象基类);
1.4.参数:无
1.5.返回值:
无法调用不会有返回值。
返回类型为T&&除非T是(可cv限定)void,在这种情况下,返回类型为T
1.6.注意:
declval只能在未评估的上下文中使用,只在编译期间生效的语句里
不需要定义,不需要类型T 拥有构造函数;评估包含此函数的表达式是错误的
1.7.备注:
表达式有两种属性:值与类型。值与类型也是两种不同的数据。
decltype作用于表达式,返回表达式类型
declval作用于类型,返回该类型的表达式(准确来说是该类型加上右值引用类型)
常用的C语言方式*(T*) nullptr 也能获得类型为T的表达式
由于不存在引用指针这种类型,所以如果T是引用类型时,
using R = int &;
//std::declval<R>()++ 表达式类型为int, ++std::declval<R>() 表达式类型为int&&
decltype(std::declval<R>()++) i=1;
//decltype(*(R*)nullptr) j = m;//错误
cout << i << endl;
2.实例:
实例1:
#include <utility>
#include <iostream>
struct A { int foo() const {return 1;}};
struct B{B() = delete;int foo() const {return 1;}};
int main(){
decltype(A().foo()) n1 = 1; // type of n1 is int
// decltype(B().foo()) n2 = n1; // 错误无默认构造函数
decltype(std::declval<B>().foo()) n2 = n1; // type of n2 is int
}
实例2:
#include <utility>
#include <iostream>
struct Base {virtual int get_x() = 0;};
class B : public Base {
public:
B(int i,int j):x(i*j){}
int get_x() {return x;}
private:
int x;
};
int main(){
decltype(std::declval<Base>().get_x()) a; // int a;
decltype(std::declval<B>().get_x()) b; // int b;
decltype(B(0,0).get_x()) c; // int c;
a = b = B(10,2).get_x();
std::cout << a << '\n';
}