C++ Decltype oraz opóźniona dekleracja typu zwracanego
int x;
decltype (x) y; // będzie tego samego typu co x
template <class T1, class T2>
void fl (T1 x, T2 y)
{
?typ? xpy = x+ y;
?
}
Rozwiązanie
decltype (x + y) xpy; // xpy będzie tego samego typu co
xpy =x + y; /// wyrazenie x + y
// lub decltype (x + y) xpy = x + y;
decltype (wyrażenie) zmienna;
Procedura wnioskowa:
Etap 1:
Jeśli wyrażenie jest prostym identyfikatorem nieujętym w nawias, to zmienna jest tego samego typu co identyfikator, z wszystkimi kwalifikatorami takimi jak const, włącznie:
double x = 5.5;
double y = 7.9;
double &ix = x;
const double *pd;
decltype (x) w; // w jest typu double
decltype (rx) u; // u jest typu double&
decltype (pd) v; // v jest typu const double*
Etap 2:
Jeśli wrażenie jest wywołanie funkcji, zmienna otrzyma typ zgodny z typpem wartosci zwróconej tej funkcji:
long indeed (int);
decltype (indeed(3))m; // m jest typu int
Etap 3:
Jeśli wyrażenie jest 1 - wartością to zmienna jest referencją do typu wyrażenia. Może się wydawać, że to regula oznacza, iż wcześniej przykład z w powinien być roztrzygnięty jako referencyjny, skoro w jest 1 - wartością. Pamiętajmy jednak, że przypadek zmiennej został załatwiony już w 1 etapie procedury i kompilator nie będzie jej kontynułował. Niniejszy etap dotyczy wyłącznie wyrażeń nie będących prostym identyfikatorami. (jak identyfikatory ujęte w nawias)
double xx = 4.4;
decltype ((xx))r2 = xx; // r2 jest typu double &
decltype ((xx))w = xx; // w jest typu double (1 etap)
Co ciekawe poza kontekstem decltype same nawiasy nie zmieniaja ani wartości, ani 1-wartościowości wyrażenia. Np.
xx = 98.6
(xx) = 98.6 // () nie wpływa na zachowanie xx
Etap 4:
Jeśli nie udało się roztrzygając typu na poprzednich etapach zmienna będzie tego samego typu co wyrażenie.
int j = 3;
int &k = j;
int &n = j;
decltype (j+6) i1 //i1 jest typu int
decltype (100L) i2 //i2 jest typu long
decltype (k+n) i3 //i3 jest typu int
Zwróćmy uwagę na chociaż k i n są referencjami, to wyrażenie k + n nie ma typu referencyjnego; to zazwyczajna suma dwóch wartości typu int.
Zastosowanie < typedet
template < class T1, class T2>
void ft (T1 x, T2 y)
{
...
typedef decltype(x+y) xy type:
xytype xpy = x+y;
xytype arr[10];
xytype &rxy = arr[2] // rxy jest referencyjny
...
}
Opóźniona deklaracja typu zwracanego
double n (int x, float y);
alternatywa
auto n (int x, float y) -> double ;
Np.
template <class T1, class T2>
auto gt (T1 x, T2 y) -> decltype (x + y)
{
...
return x+y;
...
}
decltype (x) y; // będzie tego samego typu co x
template <class T1, class T2>
void fl (T1 x, T2 y)
{
?typ? xpy = x+ y;
?
}
Rozwiązanie
decltype (x + y) xpy; // xpy będzie tego samego typu co
xpy =x + y; /// wyrazenie x + y
// lub decltype (x + y) xpy = x + y;
decltype (wyrażenie) zmienna;
Procedura wnioskowa:
Etap 1:
Jeśli wyrażenie jest prostym identyfikatorem nieujętym w nawias, to zmienna jest tego samego typu co identyfikator, z wszystkimi kwalifikatorami takimi jak const, włącznie:
double x = 5.5;
double y = 7.9;
double &ix = x;
const double *pd;
decltype (x) w; // w jest typu double
decltype (rx) u; // u jest typu double&
decltype (pd) v; // v jest typu const double*
Etap 2:
Jeśli wrażenie jest wywołanie funkcji, zmienna otrzyma typ zgodny z typpem wartosci zwróconej tej funkcji:
long indeed (int);
decltype (indeed(3))m; // m jest typu int
Etap 3:
Jeśli wyrażenie jest 1 - wartością to zmienna jest referencją do typu wyrażenia. Może się wydawać, że to regula oznacza, iż wcześniej przykład z w powinien być roztrzygnięty jako referencyjny, skoro w jest 1 - wartością. Pamiętajmy jednak, że przypadek zmiennej został załatwiony już w 1 etapie procedury i kompilator nie będzie jej kontynułował. Niniejszy etap dotyczy wyłącznie wyrażeń nie będących prostym identyfikatorami. (jak identyfikatory ujęte w nawias)
double xx = 4.4;
decltype ((xx))r2 = xx; // r2 jest typu double &
decltype ((xx))w = xx; // w jest typu double (1 etap)
Co ciekawe poza kontekstem decltype same nawiasy nie zmieniaja ani wartości, ani 1-wartościowości wyrażenia. Np.
xx = 98.6
(xx) = 98.6 // () nie wpływa na zachowanie xx
Etap 4:
Jeśli nie udało się roztrzygając typu na poprzednich etapach zmienna będzie tego samego typu co wyrażenie.
int j = 3;
int &k = j;
int &n = j;
decltype (j+6) i1 //i1 jest typu int
decltype (100L) i2 //i2 jest typu long
decltype (k+n) i3 //i3 jest typu int
Zwróćmy uwagę na chociaż k i n są referencjami, to wyrażenie k + n nie ma typu referencyjnego; to zazwyczajna suma dwóch wartości typu int.
Zastosowanie < typedet
template < class T1, class T2>
void ft (T1 x, T2 y)
{
...
typedef decltype(x+y) xy type:
xytype xpy = x+y;
xytype arr[10];
xytype &rxy = arr[2] // rxy jest referencyjny
...
}
Opóźniona deklaracja typu zwracanego
double n (int x, float y);
alternatywa
auto n (int x, float y) -> double ;
Np.
template <class T1, class T2>
auto gt (T1 x, T2 y) -> decltype (x + y)
{
...
return x+y;
...
}
Komentarze
Prześlij komentarz