Share via


decltype (C++)

Specifikátor decltype typu poskytuje typ zadaného výrazu. Specifikátor decltype typu spolu s klíčovým slovem autoje 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 parametru expression 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 typ expression. 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 avolatilethrowspecifikace 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.

autofunction_name(parametersopt)constopt 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ší.