C++11 auto 与 decltype 关键字

文章目录

auto 关键字

auto 占位类型说明符:对于变量,指定要从其初始化器自动推导出其类型
https://zh.cppreference.com/w/cpp/language/auto

编程时候常常需要把表达式的值付给变量,需要在声明变量的时候清楚的知道变量是什么类型。然而做到这一点并非那么容易(特别是模板中),有时候根本做不到。

为了解决这个问题,C++11新标准就引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。和原来那些只对应某种特定的类型说明符(例如 int)不同。auto 让编译器通过初始值来进行类型推演。从而获得定义变量的类型,所以说 auto 定义的变量必须有初始值

示例

#include <iostream>
#include <utility>
 
template<class T, class U>
auto add(T t, U u) { return t + u; } // 返回类型是 operator+(T, U) 的类型
 
// 在其所调用的函数返回引用的情况下
// 函数调用的完美转发必须用 decltype(auto)
template<class F, class... Args>
decltype(auto) PerfectForward(F fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}
 
 
int main()
{
    auto a = 1 + 2;          // a 的类型是 int
    auto b = add(1, 1.2);    // b 的类型是 double
    static_assert(std::is_same_v<decltype(a), int>);
    static_assert(std::is_same_v<decltype(b), double>);
 
    auto c0 = a;             // c0 的类型是 int,保有 a 的副本
    decltype(auto) c1 = a;   // c1 的类型是 int,保有 a 的副本
    decltype(auto) c2 = (a); // c2 的类型是 int&,它是 a 的别名
    std::cout << "通过 c2 修改前,a = " << a << '\n';
    ++c2;
    std::cout << "通过 c2 修改后,a = " << a << '\n';
 
 
    auto d = {1, 2}; // OK:d 的类型是 std::initializer_list<int>
    auto n = {5};    // OK:n 的类型是 std::initializer_list<int>
//  auto e{1, 2};    // C++17 起错误,之前是 std::initializer_list<int>
    auto m{5};       // OK:DR N3922 起 m 的类型是 int,之前是 initializer_list<int>
//  decltype(auto) z = { 1, 2 } // 错误:{1, 2} 不是表达式
 
    // auto 常用于无名类型,例如 lambda 表达式的类型
    auto lambda = [](int x) { return x + 3; };
 
//  auto int x; // 于 C++98 合法,C++11 起错误
//  auto x;     // 于 C 合法,于 C++ 错误
 
    [](...){}(c0, c1, d, n, m, lambda); // 阻止“变量未使用”警告
}

问题

  1. auto 是否可以用于函数返回类型?

decltype 关键字

https://www.cnblogs.com/QG-whz/p/4952980.html

https://zh.cppreference.com/w/cpp/language/decltype

decltype 简介

我们之前使用的typeid运算符来查询一个变量的类型,这种类型查询在运行时进行。RTTI机制为每一个类型产生一个type_info类型的数据,而typeid查询返回的变量相应type_info数据,通过name成员函数返回类型的名称。同时在C++11中typeid还提供了hash_code这个成员函数,用于返回类型的唯一哈希值。

RTTI会导致运行时效率降低,且在泛型编程中,我们更需要的是编译时就要确定类型,RTTI并无法满足这样的要求。

编译时类型推导的出现正是为了泛型编程,在非泛型编程中,我们的类型都是确定的,根本不需要再进行推导。

而编译时类型推导,除了我们说过的auto关键字,还有本文的decltype。

decltype与auto关键字一样,用于进行编译时类型推导,不过它与auto还是有一些区别的。decltype的类型推导并不是像auto一样是从变量声明的初始化表达式获得变量的类型,而是总是以一个普通表达式作为参数,返回该表达式的类型,而且decltype并不会对表达式进行求值。

decltype用法

推导出表达式类型

int i = 4;
decltype(i) a; //推导结果为int。a的类型为int。

与using/typedef合用,用于定义类型

decltype 示例

#include <iostream>
#include <type_traits>
 
struct A { double x; };
const A* a;
 
decltype(a->x) y;       // y 的类型是 double(其声明类型)
decltype((a->x)) z = y; // z 的类型是 const double&(左值表达式)
 
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // 返回类型依赖于模板形参
{                                     // C++14 开始可以推导返回类型
    return t+u;
}
 
int main() 
{
    int i = 33;
    decltype(i) j = i * 2;
 
    std::cout << "i = " << i << ", "
              << "j = " << j << '\n';
 
    std::cout << "i 和 j 的类型相同吗?"
              << (std::is_same_v<decltype(i), decltype(j)> ? "相同" : "不同") << '\n';
 
    auto f = [](int a, int b) -> int
    {
        return a * b;
    };
 
    decltype(f) g = f; // lambda 的类型是独有且无名的
    i = f(2, 2);
    j = g(3, 3);
 
    std::cout << "i = " << i << ", "
              << "j = " << j << '\n';
}

decltype 问题

  1. decltype 有啥用?项目中怎么用?使用在什么场景?

参考资料

C++11新标准:decltype关键字
https://www.cnblogs.com/cauchy007/p/4966485.html

上一篇:typedef 、auto、 decltype用法


下一篇:C++ decltype类型推导