decltype
(C++)
Specifikátor decltype
typu poskytuje typ zadaného výrazu. Specifikátor decltype
typu spolu s klíčovým slovem auto
je užitečný především vývojářům, kteří píší knihovny šablon. Použijte auto
a decltype
deklarujte šablonu funkce, jejíž návratový typ závisí na typech argumentů šablony. Nebo můžete použít auto
a decltype
deklarovat šablonu funkce, která zabalí volání jiné funkce, a poté vrátí návratový typ zabalené funkce.
Syntaxe
decltype(
expression
)
Parametry
expression
Výraz. Další informace naleznete v tématu Výrazy.
Vrácená hodnota
Typ parametru expression
.
Poznámky
Specifikátor decltype
typu je podporován v sadě Visual Studio 2010 nebo novějších verzích a lze ho použít s nativním nebo spravovaným kódem. decltype(auto)
(C++14) se podporuje v sadě Visual Studio 2015 a novějších verzích.
Kompilátor používá následující pravidla k určení typu parametru expression
.
expression
Pokud je parametr identifikátorem nebo přístupem člena třídy,decltype(expression)
je typem entity pojmenované .expression
Pokud neexistuje taková entita nebo název parametruexpression
množinu přetížených funkcí, kompilátor zobrazí chybovou zprávu.expression
Pokud je parametr voláním funkce nebo přetíženou funkcí operátoru,decltype(expression)
je návratovým typem funkce. Závorky kolem přetíženého operátoru jsou ignorovány.expression
Pokud je parametr rvalue,decltype(expression)
je typexpression
.expression
Pokud je parametr lvalue,decltype(expression)
je lvalue odkaz na typ .expression
Následující příklad kódu ukazuje některé použití specifikátoru decltype
typu. Nejprve předpokládejme, že jste naprogramovali následující příkazy.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
Dále prozkoumejte typy vrácené čtyřmi decltype
příkazy v následující tabulce.
Příkaz | Typ | Notes |
---|---|---|
decltype(fx()); |
const int&& |
Rvalue odkaz na .const int |
decltype(var); |
int |
Typ proměnné var . |
decltype(a->x); |
double |
Typ přístupu členu. |
decltype((a->x)); |
const double& |
Vnitřní závorky způsobí, že je příkaz vyhodnocen jako výraz namísto přístupu ke členu. A protože a je deklarován jako const ukazatel, typ je odkaz na const double . |
decltype
a auto
V jazyce C++14 můžete k deklaraci šablony funkce, jejíž návratový typ závisí na typech argumentů šablony, použít decltype(auto)
bez koncového návratového typu.
V jazyce C++11 můžete pomocí specifikátoru decltype
typu na koncovém návratovém typu společně s auto
klíčovým slovem deklarovat šablonu funkce, jejíž návratový typ závisí na typech argumentů šablony. Představte si například následující příklad kódu, ve kterém návratový typ šablony funkce závisí na typech argumentů šablony. V příkladu kódu zástupný symbol označuje, UNKNOWN
že návratový typ nelze zadat.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; };
Zavedení specifikátoru decltype
typu umožňuje vývojáři získat typ výrazu, který vrátí šablona funkce. Použijte alternativní syntaxi deklarace funkce, která se zobrazí později, auto
klíčové slovo a decltype
specifikátor typu k deklaraci opožděného návratového typu. Pozdní návratový typ je určen při kompilaci deklarace, nikoli při kódování.
Následující prototyp znázorňuje syntaxi alternativní deklarace funkce. Kvalifikátory const
avolatile
throw
specifikace výjimky jsou volitelné. Zástupný function_body
symbol představuje složený příkaz, který určuje, co funkce dělá. Osvědčeným postupem kódování by expression
měl zástupný symbol v decltype
příkazu odpovídat výrazu určenému příkazem return
( pokud existuje) v objektu function_body
.
auto
function_name
(
parameters
opt)
const
opt opt optvolatile
->
decltype(
expression
)
noexcept
{
function_body
};
V následujícím příkladu kódu je pozdní návratový myFunc
typ šablony funkce určen typy t
argumentů šablony a u
šablony. Osvědčeným postupem kódování je, že v příkladu kódu se také používají odkazy na hodnoty rvalue a forward
šablona funkce, které podporují dokonalé přeposílání. Další informace naleznete v tématu Deklarátor odkazu Rvalue: &>.
//C++11
template<typename T, typename U>
auto myFunc(T&& t, U&& u) -> decltype (forward<T>(t) + forward<U>(u))
{ return forward<T>(t) + forward<U>(u); };
//C++14
template<typename T, typename U>
decltype(auto) myFunc(T&& t, U&& u)
{ return forward<T>(t) + forward<U>(u); };
decltype
funkce předávání (C++11)
Funkce předávání zaobalují volání dalších funkcí. Zvažte šablonu funkce, která předává své argumenty nebo výsledky výrazu, který zahrnuje tyto argumenty, jiné funkci. Kromě toho funkce předávání vrátí výsledek volání další funkce. V tomto scénáři by měl návratový typ funkce předávání být stejný jako návratový typ zabalené funkce.
V tomto scénáři nemůžete napsat odpovídající výraz typu bez specifikátoru decltype
typu. Specifikátor decltype
typu umožňuje obecné funkce předávání, protože neztratí požadované informace o tom, jestli funkce vrací odkazový typ. Příklad kódu funkce pro předávání najdete v předchozím myFunc
příkladu šablony funkce.
Příklady
Následující příklad kódu deklaruje pozdní zadaný návratový typ šablony Plus()
funkce . Funkce Plus
zpracovává své dva operandy s přetížením operator+
. Interpretace operátoru plus (+
) a návratového Plus
typu funkce proto závisí na typech argumentů funkce.
// decltype_1.cpp
// compile with: cl /EHsc decltype_1.cpp
#include <iostream>
#include <string>
#include <utility>
#include <iomanip>
using namespace std;
template<typename T1, typename T2>
auto Plus(T1&& t1, T2&& t2) ->
decltype(forward<T1>(t1) + forward<T2>(t2))
{
return forward<T1>(t1) + forward<T2>(t2);
}
class X
{
friend X operator+(const X& x1, const X& x2)
{
return X(x1.m_data + x2.m_data);
}
public:
X(int data) : m_data(data) {}
int Dump() const { return m_data;}
private:
int m_data;
};
int main()
{
// Integer
int i = 4;
cout <<
"Plus(i, 9) = " <<
Plus(i, 9) << endl;
// Floating point
float dx = 4.0;
float dy = 9.5;
cout <<
setprecision(3) <<
"Plus(dx, dy) = " <<
Plus(dx, dy) << endl;
// String
string hello = "Hello, ";
string world = "world!";
cout << Plus(hello, world) << endl;
// Custom type
X x1(20);
X x2(22);
X x3 = Plus(x1, x2);
cout <<
"x3.Dump() = " <<
x3.Dump() << endl;
}
Plus(i, 9) = 13
Plus(dx, dy) = 13.5
Hello, world!
x3.Dump() = 42
Visual Studio 2017 a novější: Kompilátor analyzuje decltype
argumenty, když jsou šablony deklarovány místo vytvoření instance. Takže pokud se v argumentu decltype
najde nespolézená specializace, neodloží se na vytvoření instance, zpracuje se okamžitě a všechny výsledné chyby se v té době diagnostikují.
Následující příklad ukazuje takovou chybu kompilátoru, která je vyvolána v okamžiku deklarace:
#include <utility>
template <class T, class ReturnT, class... ArgsT> class IsCallable
{
public:
struct BadType {};
template <class U>
static decltype(std::declval<T>()(std::declval<ArgsT>()...)) Test(int); //C2064. Should be declval<U>
template <class U>
static BadType Test(...);
static constexpr bool value = std::is_convertible<decltype(Test<T>(0)), ReturnT>::value;
};
constexpr bool test1 = IsCallable<int(), int>::value;
static_assert(test1, "PASS1");
constexpr bool test2 = !IsCallable<int*, int>::value;
static_assert(test2, "PASS2");
Požadavky
Visual Studio 2010 nebo novější verze
decltype(auto)
vyžaduje Visual Studio 2015 nebo novější.
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro