C++11 auto and decltype keywords

auto keyword

auto placeholder type specifier: for a variable, specifies that its type is automatically derived from its initializer.
https://zh.cppreference.com/w/cpp/language/auto

When programming, you often need to pay the value of the expression to the variable, and you need to know clearly what type the variable is when declaring the variable. However, this is not so easy (especially in the template), and sometimes it can't be done at all.

In order to solve this problem, the new C++11 standard introduces the auto type specifier, which allows the compiler to analyze the type of expression for us. It is different from those that only correspond to a specific type specifier (such as int). Auto lets the compiler deduce the type through the initial value. So as to obtain the type of the defined variable, so the variable defined by auto must have an initial value.

Example

#include <iostream>
#include <utility>
 
template<class T, class U>
auto add(T t, U u) { return t + u; } // The return type is the type of operator+(T, U)
 
// When the function it calls returns a reference
// The perfect forwarding of function calls must use 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;          // The type of a is int
    auto b = add(1, 1.2);    // The type of b is double
    static_assert(std::is_same_v<decltype(a), int>);
    static_assert(std::is_same_v<decltype(b), double>);
 
    auto c0 = a;             // The type of c0 is int, keeping a copy of A
    decltype(auto) c1 = a;   // The type of c1 is int, keeping a copy of A
    decltype(auto) c2 = (a); // The type of c2 is int &, which is the alias of a
    std::cout << "adopt c2 Before modification, a = " << a << '\n';
    ++c2;
    std::cout << "adopt c2 After modification, a = " << a << '\n';
 
 
    auto d = {1, 2}; // The type of OK: d is STD:: initializer_ list<int>
    auto n = {5};    // The type of OK: n is STD:: initializer_ list<int>
//  auto e{1, 2};    //  17 errors in C + + before STD:: initializer_ list<int>
    auto m{5};       // OK: the type of m from DR N3922 is int, which was initializer before_ list<int>
//  Decltype (auto) z = {1, 2} / / error: {1, 2} is not an expression
 
    // auto is often used for anonymous types, such as the type of lambda expression
    auto lambda = [](int x) { return x + 3; };
 
//  auto int x; //  Valid in C++98, with 11 errors in C + +
//  auto x;     //  Valid in C, wrong in C + +
 
    [](...){}(c0, c1, d, n, m, lambda); // Block variable not used warning
}

problem

  1. Can auto be used for function return types?

decltype keyword

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

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

decltype introduction

We previously used the typeid operator to query the type of a variable, which is performed at run time. The RTTI mechanism generates a type for each type_info type data, and the variable returned by typeid query corresponds to type_info data, which returns the name of the type through the name member function. At the same time, in C++11, typeid also provides hash_code is a member function that returns a unique hash value of a type.

RTTI will reduce the efficiency of runtime, and in generic programming, we need to determine the type at compile time. RTTI cannot meet this requirement.

The emergence of type derivation at compile time is just for generic programming. In non generic programming, our types are determined and there is no need to deduce at all.

For compile time type derivation, in addition to the auto keyword we mentioned, there is also decltype in this paper.

Decltype, like the auto keyword, is used for compile time type derivation, but it is still different from auto. The type derivation of decltype does not obtain the type of variable from the initialization expression declared by the variable like auto, but always takes an ordinary expression as a parameter to return the type of the expression, and decltype does not evaluate the expression.

decltype usage

Derived expression type

int i = 4;
decltype(i) a; //The derivation result is int. The type of a is int.

Used with using/typedef to define types

decltype example

#include <iostream>
#include <type_traits>
 
struct A { double x; };
const A* a;
 
decltype(a->x) y;       // The type of y is double (its declaration type)
decltype((a->x)) z = y; // The type of z is const double & (lvalue expression)
 
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // The return type depends on the template parameter
{                                     // C++14 can deduce the return type
    return t+u;
}
 
int main() 
{
    int i = 33;
    decltype(i) j = i * 2;
 
    std::cout << "i = " << i << ", "
              << "j = " << j << '\n';
 
    std::cout << "i and j Are they of the same type?"
              << (std::is_same_v<decltype(i), decltype(j)> ? "identical" : "Different") << '\n';
 
    auto f = [](int a, int b) -> int
    {
        return a * b;
    };
 
    decltype(f) g = f; // The type of lambda is unique and nameless
    i = f(2, 2);
    j = g(3, 3);
 
    std::cout << "i = " << i << ", "
              << "j = " << j << '\n';
}

decltype problem

  1. What's the use of decltype? How to use it in the project? In what scenario?

reference material

New C++11 standard: decltype keyword
https://www.cnblogs.com/cauchy007/p/4966485.html

Keywords: C++

Added by chris davies on Sat, 11 Dec 2021 12:58:11 +0200