Suche…


Bemerkungen

Im November 2014 verabschiedete das C ++ Standardization Committee den Vorschlag N3922, der die spezielle Typabzugsregel für Auto- und Braced-Initialisierer mit direkter Initialisierungssyntax beseitigt. Dies ist nicht Teil des C ++ - Standards, wurde jedoch von einigen Compilern implementiert.

Vorlagenparameterabzug für Konstruktoren

Vor C ++ 17 kann ein Vorlagenabzug den Klassentyp für Sie nicht in einem Konstruktor ableiten. Es muss explizit angegeben werden. Manchmal können diese Typen jedoch sehr umständlich sein oder (im Fall von Lambdas) nicht benannt werden. make_pair() wir eine make_pair() make_tuple() wie make_pair() , make_tuple() , back_inserter() usw.) erhalten.

C ++ 17

Das ist nicht mehr nötig:

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)>

Es wird angenommen, dass Konstruktoren die Klassenvorlagenparameter ableiten. In einigen Fällen reicht dies jedoch nicht aus, und wir können explizite Abzugshilfen bereitstellen:

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>

Vorlagentyp Abzug

Generische Vorlagen-Syntax

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

f(expr);

Fall 1: ParamType ist eine Referenz oder ein Zeiger, jedoch keine Universal- oder Weiterleitungsreferenz. In diesem Fall funktioniert der Typabzug auf diese Weise. Der Compiler ignoriert den Referenzteil, wenn er in expr . Der Compiler expr den Typ von ParamType mit ParamType und der Bestimmung von T ParamType .

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 ist eine Universalreferenz oder ParamType . In diesem Fall ist der expr derselbe wie in Fall 1, wenn der expr ein r- expr ist. Wenn expr ein lvalue ist, werden sowohl T als auch ParamType als lvalue-Referenzen abgeleitet.

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 ist weder ein Zeiger noch eine Referenz. Wenn expr eine Referenz ist, wird der Referenzteil ignoriert. Wenn expr const ist, wird dies ebenfalls ignoriert. Wenn es flüchtig ist, wird es auch ignoriert, wenn der Typ von T abgeleitet wird.

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

Automatischer Typabzug

C ++ 11

Der Typabzug mit dem Schlüsselwort auto funktioniert fast genauso wie der Abzug des Vorlagentyps. Nachfolgend einige Beispiele:

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&&

Die Unterschiede sind nachfolgend aufgeführt:

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>

Wie Sie sehen, wenn Sie geschweifte Initialisierer verwenden, wird auto dazu gezwungen, eine Variable vom Typ std::initializer_list<T> zu erstellen. Wenn der T , wird der Code abgelehnt.

Wenn auto als Rückgabetyp einer Funktion verwendet wird, wird angegeben, dass die Funktion einen nachgestellten Rückgabetyp hat .

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

C ++ 14 erlaubt zusätzlich zu den in C ++ 11 zugelassenen Verwendungen von auto Folgendes:

  1. Bei Verwendung als Rückgabetyp einer Funktion ohne nachgestellten Rückgabetyp wird angegeben, dass der Rückgabetyp der Funktion aus den Rückgabeanweisungen im Rumpf der Funktion (sofern vorhanden) abgeleitet werden soll.

    // f returns int:
    auto f() { return 42; }
    // g returns void:
    auto g() { std::cout << "hello, world!\n"; }
    
  2. Bei Verwendung im Parametertyp eines Lambda wird das Lambda als generisches Lambda definiert .

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

Das spezielle Formular decltype(auto) leitet einen Typ unter Verwendung der decltype von decltype und nicht von auto .

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

In C ++ 03 und früheren Versionen hatte das Schlüsselwort auto eine völlig andere Bedeutung als ein von C geerbter Speicherklassenspezifizierer .



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow