C++笔记 - decltype

356 阅读1分钟

decltype能够获取一个表达式的类型。而auto关键字是在赋值时获取变量的类型。decltype的一般用法:int a = 0; decltype(i) b = 0;

decltype的用途:

  • 定义新类型:

    using nullptr_t = decltype(nullptr);
    
  • 获取匿名类型:

    struct {
        int m_a;
    } num = {.m_a = 0,};
    decltype(num) b;
    
  • 在泛型编程中与auto关键字结合,实现类型自动推倒:

    #include <iostream>
    
    template <typename T, typename U>
    auto add(T x, U y)->decltype(x + y) {
        return x + y;
    }
    
    int main() {
        std::cout << add(1, 2.3) << std::endl; // 输出:3.3
    }
    

decltype类型推倒规则:

  • 不适用于重载函数。

  • 实体类型:没有带括号的标记符表达式或类成员访问表达式。

    int i = 0;
    decltype(i) a = 0; // int
    
    int arr[2] = {0};
    decltype(arr) a = {0, 1}; // int(a)[2] = {0, 1};
    
    int *ptr = nullptr;
    decltype(ptr) a = nullptr; // int*
    
    struct num {int m_a;}n;
    decltype(n.m_a) a = 0; // int
    
  • 实体类型&&:将亡值。

    int&& right_value_reference(){};
    decltype(right_value_reference()) a = 1; // int&&
    
  • 实体类型&:左值。

    int i = 0;
    int *ptr = nullptr;
    decltype((i)) a = 0; // int&
    decltype (++i) a = 0; //int&  ++i返回i的左值
    decltype(arr[5]) a = 0;//int& []操作返回左值
    decltype(*ptr) a = 0;//int& *操作返回左值
    decltype("hello") a = "world"; // 符串字面常量为const左值
    
  • 实体类型:上述情况都不是。

    int i = 0;
    decltype(1) a = 0; //const int
    decltype(Func(1)) a = true;//const bool
    decltype(i++) a = 0; //int i++返回右值
    

注意:

  • 非字符串字面量常量为右值,使用最后一条规则。

  • 可通过std::is_lvalue_reference<decltype(++i)>::valuestd::is_rvalue_reference<decltype(++i)>::value 判断一个表达是左值还是右值。例子:

    #include <iostream>
    #include <type_traits>
    
    int main() {
        int i = 0;
        std::cout << std::is_lvalue_reference<decltype(++i)>::value << std::endl; // 输出:1
        std::cout << std::is_rvalue_reference<decltype(++i)>::value << std::endl; // 输出:0
    }