C++
type aftrek
Zoeken…
Opmerkingen
In november 2014 keurde het C ++ Standaardisatiecomité voorstel N3922 goed, dat de speciale aftrekregel voor automatische en schrap initialisatoren elimineert met behulp van directe initialisatiesyntaxis. Dit maakt geen deel uit van de C ++ standaard maar is door sommige compilers geïmplementeerd.
Sjabloonparameteraftrek voor constructeurs
Voorafgaand aan C ++ 17 kan sjabloonaftrek het klasse-type niet voor u afleiden in een constructor. Het moet expliciet worden gespecificeerd. Soms kunnen deze typen echter erg omslachtig zijn of (in het geval van lambdas) onmogelijk te noemen, dus kregen we een proliferatie van make_pair()
zoals make_pair()
, make_tuple()
, back_inserter()
, etc.).
Dit is niet langer nodig:
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)>
Constructeurs worden geacht de parameters van de klassensjabloon af te leiden, maar in sommige gevallen is dit onvoldoende en kunnen we expliciete deductiegidsen bieden:
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>
Sjabloontype Aftrek
Sjabloon generieke syntaxis
template<typename T>
void f(ParamType param);
f(expr);
Geval 1: ParamType
is een referentie of aanwijzer, maar geen universele of voorwaartse referentie. In dit geval werkt typeaftrek op deze manier. De compiler negeert het referentiedeel als het in expr
bestaat. De compiler dan patroon-wedstrijden expr
het type 's tegen ParamType
op de aanwijzing 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&
Geval 2: ParamType
is een Universal Reference of Forward Reference. In dit geval is de type-aftrek hetzelfde als in geval 1 als de expr
is. Als expr
is, worden zowel T
als ParamType
afgeleid als ParamType
.
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&&
Geval 3: ParamType
is noch een aanwijzer noch een referentie. Als expr
een referentie is, wordt het referentiedeel genegeerd. Als expr
const is, wordt dat ook genegeerd. Als het vluchtig is, wordt dat ook genegeerd bij het afleiden van het type van 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
Auto Type Aftrek
Type aftrek met behulp van het auto
trefwoord werkt bijna hetzelfde als Sjabloon Type aftrek. Hieronder enkele voorbeelden:
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&&
De verschillen worden hieronder beschreven:
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>
Zoals je kunt zien als je accolades gebruikt, wordt auto gedwongen een variabele van het type std::initializer_list<T>
. Als het niet uit T
kan afleiden, wordt de code afgewezen.
Wanneer auto
wordt gebruikt als het retourtype van een functie, geeft dit aan dat de functie een volgend retourtype heeft .
auto f() -> int {
return 42;
}
C ++ 14 staat, naast het gebruik van auto toegestaan in C ++ 11, het volgende toe:
Wanneer het wordt gebruikt als het retourtype van een functie zonder een volgend retourtype, geeft dit op dat het retourtype van de functie moet worden afgeleid uit de retourinstructies in de hoofdtekst van de functie, indien aanwezig.
// f returns int: auto f() { return 42; } // g returns void: auto g() { std::cout << "hello, world!\n"; }
Wanneer gebruikt in het parametertype van een lambda, definieert de lambda een generieke lambda .
auto triple = [](auto x) { return 3*x; }; const auto x = triple(42); // x is a const int with value 126
De speciale vorm decltype(auto)
leidt een type af met behulp van de regels voor decltype
van decltype
plaats van die van 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 en eerder had het auto
sleutelwoord een heel andere betekenis als een opslagklasse-aanduiding die werd overgenomen van C.