跳转至

declval

  • 头文件:utility
  • 功能:declval是一个模板函数,常与decltype一起使用,令在 decltype 表达式中不必经过构造函数就能使用成员函数
  • 注意:因为declval只有声明没有定义,因此只能用在不求值语境,所以可以用在decltype
  • 示例
#include <utility>
#include <iostream>

struct Default { int foo() const { return 1; } };

struct NonDefault
{
    NonDefault() = delete;
    string m_str;
    int foo() const { return 1; }
};

int main()
{
    decltype(Default().foo()) n1 = 1;                   // n1 的类型是 int
//  decltype(NonDefault().foo()) n2 = n1;               // 错误:无默认构造函数
    decltype(std::declval<NonDefault>().foo()) n2 = n1; // n2 的类型是 int
    decltype(std::declval<NonDefault>().m_str) n3;      //n3的类型是string
    decltype(std::declval<Default>()) n4=Default();     //n4是Default&&类型,declval返回的就是右值引用
}
  • 源码分析:模板函数declval(只声明不定义)最终返回的是_Ty右值引用类型
// STRUCT TEMPLATE _Add_reference
template <class _Ty, class = void>
struct _Add_reference { // add reference (non-referenceable type)
    using _Lvalue = _Ty;
    using _Rvalue = _Ty;
};
//具体化版本,匹配<_Ty,void>类型或省略第二参数<_Ty>
template <class _Ty>
struct _Add_reference<_Ty, std::void_t<_Ty&>> { // (referenceable type)
    using _Lvalue = _Ty&;
    using _Rvalue = _Ty&&;
};
template <class _Ty>
using add_rvalue_reference_t = typename _Add_reference<_Ty>::_Rvalue;

// FUNCTION TEMPLATE declval
template <class _Ty>
add_rvalue_reference_t<_Ty> declval() noexcept;