Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Specyfikator decltype typu zwraca typ określonego wyrażenia. Specyfikator decltype typu wraz ze auto słowem kluczowym jest przydatny głównie dla deweloperów, którzy piszą biblioteki szablonów. Użyj auto funkcji i decltype , aby zadeklarować szablon funkcji, którego typ zwracany zależy od typów argumentów szablonu. Możesz też użyć polecenia auto i decltype zadeklarować szablon funkcji, który opakowuje wywołanie innej funkcji, a następnie zwraca zwracany typ opakowanej funkcji.
Składnia
decltype(expression)
Parametry
expression
Wyrażenie. Aby uzyskać więcej informacji, zobacz Expressions.
Wartość zwracana
Typ parametru expression .
Uwagi
Specyfikator decltype typu jest obsługiwany w programie Visual Studio 2010 lub nowszych wersjach i może być używany z kodem natywnym lub zarządzanym.
decltype(auto) (C++14) jest obsługiwany w programie Visual Studio 2015 lub nowszym.
Kompilator używa następujących reguł, aby określić typ parametru expression .
expressionJeśli parametr jest identyfikatorem lub dostępem do składowej klasy,decltype(expression)jest typem jednostki o nazwie .expressionJeśli nie ma takiej jednostki lubexpressionparametrów nazw zestaw przeciążonych funkcji, kompilator zwraca komunikat o błędzie.expressionJeśli parametr jest wywołaniem funkcji lub przeciążonej funkcji operatora,decltype(expression)jest zwracanym typem funkcji. Nawiasy wokół przeciążonego operatora są ignorowane.expressionJeśli parametr jest rvalue,decltype(expression)jest typemexpression.expressionJeśli parametr jest lvalue,decltype(expression)jest odwołaniem lvalue do typuexpression.
W poniższym przykładzie kodu pokazano niektóre zastosowania specyfikatora decltype typu. Najpierw załóżmy, że kodowane są następujące instrukcje.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
Następnie sprawdź typy zwracane przez cztery decltype instrukcje w poniższej tabeli.
| Wypowiedź | Typ | Notatki |
|---|---|---|
decltype(fx()); |
const int&& |
Odwołanie rvalue do elementu const int. |
decltype(var); |
int |
Typ zmiennej var. |
decltype(a->x); |
double |
Typ dostępu do elementu członkowskiego. |
decltype((a->x)); |
const double& |
Nawiasy wewnętrzne powodują, że instrukcja ma być oceniana jako wyrażenie zamiast dostępu do elementu członkowskiego. A ponieważ a jest zadeklarowany jako const wskaźnik, typ jest odwołaniem do const double. |
decltype i auto
W języku C++14 można użyć bez decltype(auto) typu powrotu końcowego, aby zadeklarować szablon funkcji, którego typ zwracany zależy od typów argumentów szablonu.
W języku C++11 można użyć decltype specyfikatora typu końcowego zwracanego wraz ze auto słowem kluczowym, aby zadeklarować szablon funkcji, którego typ zwracany zależy od typów argumentów szablonu. Rozważmy na przykład następujący przykład kodu, w którym zwracany typ szablonu funkcji zależy od typów argumentów szablonu. W przykładzie kodu symbol zastępczy wskazuje, UNKNOWN że nie można określić typu zwracanego.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; }
Wprowadzenie specyfikatora decltype typu umożliwia deweloperowi uzyskanie typu wyrażenia zwracanego przez szablon funkcji. Użyj składni deklaracji funkcji alternatywnej , która jest wyświetlana później, auto słowo kluczowe i decltype specyfikator typu, aby zadeklarować późno określony typ zwracany. Określony późno typ zwracany jest określany podczas kompilowania deklaracji, a nie podczas jego kodowania.
Poniższy prototyp ilustruje składnię alternatywnej deklaracji funkcji. Kwalifikatory const i volatile oraz specyfikacja wyjątkuthrow są opcjonalne. Symbol function_body zastępczy reprezentuje instrukcję złożoną, która określa, co robi funkcja. Najlepszym rozwiązaniem expression w zakresie kodowania jest dopasowanie symbolu zastępczego w instrukcji decltype do wyrażenia określonego przez instrukcję return , jeśli istnieje, w elemecie function_body.
auto
function_name
(
parameters
Zdecydować)constZdecydowaćvolatileZdecydować->decltype(expression)noexceptZdecydować{function_body};
W poniższym przykładzie kodu typ zwracany późno określony szablon myFunc funkcji jest określany przez typy t argumentów i u szablonu. Najlepszym rozwiązaniem w zakresie kodowania jest również użycie odwołań rvalue i szablonu forward funkcji, które obsługują doskonałe przekazywanie. Aby uzyskać więcej informacji, zobacz Deklarator odwołań 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 funkcje przekazywania (C++11)
Funkcje przekazujące zawijają wywołania do innych funkcji. Rozważ szablon funkcji, który przekazuje swoje argumenty lub wyniki wyrażenia, które obejmuje te argumenty, do innej funkcji. Ponadto funkcja przekazywania zwraca wynik wywoływania innej funkcji. W tym scenariuszu zwracany typ funkcji przekazywania powinien być taki sam jak zwracany typ opakowanej funkcji.
W tym scenariuszu nie można napisać odpowiedniego wyrażenia typu bez specyfikatora decltype typu. Specyfikator decltype typu włącza ogólne funkcje przekazywania, ponieważ nie traci wymaganych informacji o tym, czy funkcja zwraca typ odwołania. Przykładowy kod funkcji przekazywania można znaleźć w przykładzie poprzedniego myFunc szablonu funkcji.
Przykłady
Poniższy przykład kodu deklaruje późno określony typ zwracany szablonu Plus()funkcji . Funkcja Plus przetwarza dwa operandy z operator+ przeciążeniem. Dlatego interpretacja operatora plus (+) i zwracanego typu Plus funkcji zależy od typów argumentów funkcji.
// 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
Program Visual Studio 2017 lub nowszy: Kompilator analizuje decltype argumenty, gdy szablony są deklarowane, a nie tworzone wystąpienia. Tak więc, jeśli specjalizacja nie zależna zostanie znaleziona w argumencie decltype , nie zostanie odroczona do czasu utworzenia wystąpienia; jest ona przetwarzana natychmiast i wszelkie błędy wynikowe są diagnozowane w tym czasie.
W poniższym przykładzie pokazano taki błąd kompilatora, który jest zgłaszany w momencie deklaracji:
#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");
Wymagania
Visual Studio 2010 lub nowsze wersje.
decltype(auto) program wymaga programu Visual Studio 2015 lub nowszego.