[C++11] decltype 完整解析

说明:decltype是“declare type”的缩写,译为“声明类型”,它是 C++11 引入的一个关键字,它的主要含义和概念是用于查询表达式的类型。decltype 能够推导出表达式的类型,包括所有的 cv-限定词(const、volatile)和引用限定词,但不包括表达式本身的值。这使得 decltype 成为模板元编程和类型推导中一个非常有用的工具。

decltype 的一些关键点解读如下:

  • 表达式类型的推导:decltype 可以用来推导几乎任何表达式的类型,包括变量、函数调用、解引用操作符、成员访问等。它推导的类型是表达式的静态类型,而不是运行时类型。
  • 保留 cv-限定词:与 auto 不同,decltype 在推导类型时会保留表达式的 const 和 volatile 属性。这意味着 decltype 可以推导出更精确的类型。
  • 不推导表达式的值:decltype 只关注表达的类型,而不关心表达式的值。因此,它可以用来推导不产生值的表达式(如函数调用或对象创建)的类型。
  • decltype 与 decltype specifier:decltype 还可以用作模板参数的 specifier,这允许模板根据其参数的类型来推导其他模板参数的类型。
  • 推导 Lambda 表达式的类型:decltype 可以用来推导 Lambda 表达式的类型,这在泛型编程中非常有用。

总的来说,decltype 是 C++11 中一个强大的类型推导工具,它提供了一种精确和灵活的方式来查询和推导表达式的类型。这在模板编程、泛型编程以及需要精确控制类型的情况下非常有用。接下来我们详细了解下,为什么有了auto关键词,还要引入decltype。

1 为什么有了auto关键词,还要引入decltype?

decltype 是 C++11 标准中引入的一个类型推导关键字,它用于查询表达式的类型。尽管 auto 也用于类型推导,但 decltype 和 auto 在用法和目的上有明显的区别。以下是引入 decltype 的一些主要原因和它与 auto 的对比:

  • 类型推导的精确性:decltype 用于推导表达式的确切类型,包括顶层 const、volatile、引用和指针等属性。而 auto 类型推导并不考虑这些属性,它推导的是表达式的底层类型(去除顶层 const、volatile、引用等)。
  • 与函数声明的兼容性:decltype 在推导类型时,不会推导函数的参数类型为可变参数模板(例如 std::declval<Args...>()),这使得 decltype 能够与函数声明兼容,而 auto 不能。
  • 推导复杂表达式的类型:decltype 可以用来推导复杂表达式的类型,包括函数调用、解引用和成员访问等。而 auto 仅用于变量声明和函数返回类型推导,不适用于表达式。
  • 模板元编程:decltype 在模板元编程中非常有用,因为它可以推导模板参数的确切类型,包括所有修饰符。这在模板特化和模板元编程中非常重要。
  • Lambda 表达式:decltype 可以用于推导 Lambda 表达式的类型,这在编写泛型代码时非常有用。而 auto 无法直接用于 Lambda 表达式的类型推导。

以下是一个简单的示例,展示了 decltype 和 auto 的不同用法:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 使用 auto 推导变量类型
    auto it = v.begin(); // it 的类型是 std::vector<int>::iterator

    // 使用 decltype 推导表达式类型
    decltype(v.begin()) it2 = v.begin(); // it2 的类型是 std::vector<int>::iterator

    // 使用 decltype 推导函数调用的类型
    auto func() -> decltype(v.size()) { // 函数返回类型是 std::vector<int>::size_type
        return v.size();
    }

    return 0;
}

在这个例子中,auto 被用于推导 it 的类型,而 decltype 被用于推导 it2 的类型和函数 func 的返回类型。注意,decltype 在推导 it2 类型时保留了 v.begin() 的所有属性,而 auto 仅推导了底层类型。

针对于使用 decltype 推导函数调用的类型中,如果没有 decltype,auto 会推导出 v.size() 的底层类型(即不包含任何顶层 const 或引用),这可能是 size_t(注意:std::vector<int>::size_type是 v.size() 的确切返回类型。在 std::vector 的情况下,size_type 是一个无符号整数类型,足以表示任何 std::vector 的大小。这个类型包含了 const 属性(因为 v 是一个 const 向量),这意味着 func 将返回一个 const 引用类型的 size_type)。

总结来说,decltype 提供了一种更精确和灵活的方式来推导表达式的类型,特别是在处理复杂表达式和模板元编程时。虽然 auto 也可以用于类型推导,但它的功能和应用场景与 decltype 不同。两者在 C++11 中共同存在,为程序员提供了更多的选择和灵活性。

2 decltype使用详解

decltype 是 C++11 中引入的一个关键字,用于推导表达式的类型。以下是一些详细的例子,展示了 decltype 在不同场景下的用法:

2.1 推导变量类型

参考代码如下:

int x = 5;
decltype(x) y = 10; // y 的类型与 x 相同,即 int

在这个例子中,decltype(x) 推导出了变量 x 的类型,即 int。然后,我们用这个类型来声明另一个变量 y。

2.2 推导函数返回类型

参考代码如下:

int foo() {
    return 42;
}

decltype(foo()) f; // f 的类型是 int

这里,decltype(foo()) 推导出了函数 foo 的返回类型,即 int。然后,我们用这个类型来声明一个变量 f。

2.3 推导复杂表达式的类型

参考代码如下:

std::vector<int> v = {1, 2, 3, 4, 5};
decltype(v.size()) sz; // sz 的类型是 std::vector<int>::size_type

在这个例子中,decltype(v.size()) 推导出了 v.size() 的类型,即 std::vector<int>::size_type。这是一个与 size_t 相似的类型,但可能包含 const 修饰符。

2.4 推导 Lambda 表达式的类型

参考代码如下:

auto lambda = [](int x, int y) -> decltype(x + y) {
    return x + y;
};

这里,decltype(x + y) 推导出了 x + y 表达式的类型,这个类型是 int。然后,这个类型被用作 Lambda 表达式的返回类型。

2.5 推导成员变量的类型

参考代码如下:

struct MyStruct {
    double d;
};

MyStruct myStruct;
decltype(myStruct.d) d; // d 的类型是 double

在这个例子中,decltype(myStruct.d) 推导出了 myStruct.d 的类型,即 double。然后,我们用这个类型来声明一个变量 d。

2.6 推导函数调用的类型(模板函数)

参考代码如下:

template <typename T>
T add(T a, T b) {
    return a + b;
}

decltype(add(1, 2)) result; // result 的类型是 int

在这个例子中,decltype(add(1, 2)) 推导出了 add 函数调用的类型,即 int。然后,我们用这个类型来声明一个变量 result。

2.7 推导类型转换的结果

参考代码如下:

double pi = 3.14159;
decltype(static_cast<int>(pi)) piAsInt;

这里,decltype(static_cast<int>(pi)) 推导出了 static_cast<int>(pi) 的类型,即 int。然后,我们用这个类型来声明一个变量 piAsInt。

2.8 推导结构体中成员的类型

参考代码如下:

struct Point {
    int x;
    double y;
};

decltype(Point{}.x) x; // x 的类型是 int
decltype(Point{}.y) y; // y 的类型是 double

在这个例子中,decltype(Point{}.x) 和 decltype(Point{}.y) 分别推导出了 Point 结构体中 x 和 y 成员的类型。

通过这些例子,我们可以看到 decltype 在 C++11 中的多样性和实用性。它不仅可以简化代码,还可以提高代码的可读性和可维护性。decltype 的引入为 C++ 编程带来了更多的灵活性和便利。

  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值