Sök…


Anmärkningar

I november 2014 antog C ++ standardiseringskommittén förslag N3922, vilket eliminerar den särskilda avdragsregeln för auto- och avstängda initialiseringar med syntax för direktinitiering. Detta är inte en del av C ++ -standarden men har implementerats av vissa kompilatorer.

Avdrag för mallparameter för konstruktörer

Innan C ++ 17 kan mallavdrag inte dra av klasstypen för dig i en konstruktör. Det måste anges uttryckligen. Ibland kan emellertid dessa typer vara mycket besvärliga eller (i fallet med lambdas) omöjliga att namnge, så vi fick en spridning av make_pair() som make_pair() , make_tuple() , back_inserter() , etc.).

C ++ 17

Detta är inte längre nödvändigt:

std::pair p(2, 4.5);     // std::pair<int, double>
std::tuple t(4, 3, 2.5); // std::tuple<int, int, double>
std::copy_n(vi1.begin(), 3,
    std::back_insert_iterator(vi2)); // constructs a back_insert_iterator<std::vector<int>>
std::lock_guard lk(mtx); // std::lock_guard<decltype(mtx)>

Konstruktörer anses härleda klassens mallparametrar, men i vissa fall är detta otillräckligt och vi kan tillhandahålla tydliga avdragsguider:

template <class Iter>
vector(Iter, Iter) -> vector<typename iterator_traits<Iter>::value_type>

int array[] = {1, 2, 3};
std::vector v(std::begin(array), std::end(array)); // deduces std::vector<int>

Malltyp Avdrag

Mall generisk syntax

template<typename T>
void f(ParamType param);

f(expr);

Fall 1: ParamType är en referens eller pekare, men inte en universell eller framåtreferens. I detta fall fungerar typavdrag på detta sätt. Kompilatorn ignorerar referensdelen om den finns i expr . Kompilatorn matchar sedan mönster från expr mot ParamType och bestämmer T

template<typename T>
void f(T& param);      //param is a reference

int x = 27;            // x is an int
const int cx = x;      // cx is a const int
const int& rx = x;     // rx is a reference to x as a const int

f(x);                  // T is int, param's type is int&
f(cx);                 // T is const int, param's type is const int&
f(rx);                 // T is const int, param's type is const int&

Fall 2: ParamType är en universell referens eller framåtreferens. I detta fall är expr detsamma som i fall 1 om expr är en ränta. Om expr är en lvalue, ParamType både T och ParamType till att vara lvalue-referenser.

template<typename T>
void f(T&& param);     // param is a universal reference

int x = 27;            // x is an int
const int cx = x;      // cx is a const int
const int& rx = x;     // rx is a reference to x as a const int

f(x);                  // x is lvalue, so T is int&, param's type is also int&
f(cx);                 // cx is lvalue, so T is const int&, param's type is also const int&
f(rx);                 // rx is lvalue, so T is const int&, param's type is also const int&
f(27);                 // 27 is rvalue, so T is int, param's type is therefore int&&

Fall 3: ParamType är varken en pekare eller en referens. Om expr är en referens ignoreras referensdelen. Om expr är const så ignoreras också. Om det är flyktigt som också ignoreras när man drar av T: s typ.

template<typename T>
void f(T param);       // param is now passed by value

int x = 27;            // x is an int
const int cx = x;      // cx is a const int
const int& rx = x;     // rx is a reference to x as a const int

f(x);                  // T's and param's types are both int
f(cx);                 // T's and param's types are again both int
f(rx);                 // T's and param's types are still both int

Auto Type Deduction

C ++ 11

Typavdrag med hjälp av auto nyckelordet fungerar nästan samma som Avdrag för malltyp. Nedan följer några exempel:

auto x = 27;           // (x is neither a pointer nor a reference), x's type is int
const auto cx = x;     // (cx is neither a pointer nor a reference), cs's type is const int
const auto& rx = x;    // (rx is a non-universal reference), rx's type is a reference to a const int

auto&& uref1 = x;      // x is int and lvalue, so uref1's type is int&
auto&& uref2 = cx;     // cx is const int and lvalue, so uref2's type is const int &
auto&& uref3 = 27;     // 27 is an int and rvalue, so uref3's type is int&&

Skillnaderna anges nedan:

auto x1 = 27;          // type is int, value is 27
auto x2(27);           // type is int, value is 27
auto x3 = { 27 };      // type is std::initializer_list<int>, value is { 27 }
auto x4{ 27 };         // type is std::initializer_list<int>, value is { 27 }
                       // in some compilers type may be deduced as an int with a 
                       // value of 27. See remarks for more information.
auto x5 = { 1, 2.0 }   // error! can't deduce T for std::initializer_list<t>

Som du kan se om du använder avstängda initialiseringar tvingas auto att skapa en variabel av typen std::initializer_list<T> . Om den inte kan dra av T , avvisas koden.

När auto används som returtyp för en funktion, anger den att funktionen har en bakre returtyp .

auto f() -> int {
    return 42;
}
C ++ 14

C ++ 14 tillåter, förutom användningen av auto tillåtna i C ++ 11, följande:

  1. När den används som returtyp för en funktion utan släpningstyp, anger du att funktionens returtyp ska härledas från returrätten i funktionens kropp, om någon.

    // f returns int:
    auto f() { return 42; }
    // g returns void:
    auto g() { std::cout << "hello, world!\n"; }
    
  2. När den används i parametertypen för en lambda, definierar den lambda som en generisk lambda .

    auto triple = [](auto x) { return 3*x; };
    const auto x = triple(42); // x is a const int with value 126
    

Den speciella formen decltype(auto) drar en typ med hjälp av decltype för decltype snarare än för auto .

int* p = new int(42);
auto x = *p;           // x has type int
decltype(auto) y = *p; // y is a reference to *p

I C ++ 03 och tidigare hade auto nyckelordet en helt annan betydelse som en lagringsklassspecifikator som ärvdes från C.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow