Szukaj…


Uwagi

W listopadzie 2014 r. Komitet Normalizacyjny C ++ przyjął propozycję N3922, która eliminuje specjalną zasadę dedukcji typów dla inicjatorów automatycznych i wzmocnionych przy użyciu składni bezpośredniej inicjalizacji. Nie jest to część standardu C ++, ale zostało zaimplementowane przez niektóre kompilatory.

Odliczenie parametru szablonu dla konstruktorów

W wersjach wcześniejszych niż C ++ 17 odliczenie szablonu nie może wywnioskować dla ciebie typu klasy w konstruktorze. Musi być wyraźnie określony. Czasami jednak typy te mogą być bardzo kłopotliwe lub (w przypadku lambdas) niemożliwe do nazwania, więc mamy do czynienia z make_pair() fabryk typów (takich jak make_pair() , make_tuple() , back_inserter() itp.).

C ++ 17

To nie jest już konieczne:

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

Konstruktorzy są uznawani za wywnioskujących parametry szablonu klasy, ale w niektórych przypadkach jest to niewystarczające i możemy zapewnić wyraźne wskazówki dedukcyjne:

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>

Odliczenie typu szablonu

Ogólna składnia szablonu

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

f(expr);

Przypadek 1: ParamType jest odwołaniem lub wskaźnikiem, ale nie jest odniesieniem uniwersalnym ani do przodu. W takim przypadku odliczenie typu działa w ten sposób. Kompilator ignoruje część odniesienia, jeśli istnieje w expr . Kompilator następnie dopasowuje wzorzec typu expr względem ParamType do określenia 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&

Przypadek 2: ParamType jest odniesieniem uniwersalnym lub odniesieniem do przodu. W tym przypadku odliczenie typu jest takie samo, jak w przypadku 1, jeśli expr jest wartością. Jeśli expr jest wartością, zarówno T , jak i ParamTypeParamType za odniesienia do wartości.

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

Przypadek 3: ParamType nie jest ani wskaźnikiem, ani odniesieniem. Jeśli expr jest odniesieniem, część odniesienia jest ignorowana. Jeśli expr jest stałą, to również jest ignorowane. Jeśli jest niestabilny, jest również ignorowany przy dedukcji typu T.

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

Odliczenie typu automatycznego

C ++ 11

Odliczanie typu za pomocą słowa kluczowego auto działa prawie tak samo, jak Odliczanie typu szablonu. Poniżej znajduje się kilka przykładów:

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

Różnice są przedstawione poniżej:

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>

Jak widać, jeśli używasz inicjowanych stężeń, auto jest zmuszone do utworzenia zmiennej typu std::initializer_list<T> . Jeśli nie można wywnioskować z T , kod jest odrzucany.

Gdy auto jest używane jako typ zwracany przez funkcję, określa, że funkcja ma końcowy typ zwracany .

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

C ++ 14 oprócz użycia funkcji auto dozwolonych w C ++ 11 umożliwia:

  1. Gdy jest używany jako typ zwracany przez funkcję bez końcowego typu zwracanego, określa, że typ zwracany przez funkcję powinien być wywnioskowany z instrukcji return w treści funkcji, jeśli takie istnieją.

    // f returns int:
    auto f() { return 42; }
    // g returns void:
    auto g() { std::cout << "hello, world!\n"; }
    
  2. W przypadku zastosowania w parametrze typu lambda, definiuje lambda jako ogólną lambda .

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

Specjalna forma decltype(auto) dedukuje typ, używając reguł dedukcji typu decltype zamiast reguł auto .

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

W C ++ 03 i wcześniejszych słowo kluczowe auto miało zupełnie inne znaczenie jako specyfikator klasy pamięci, który został odziedziczony z C.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow