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;
...
}

Komentarze

Popularne posty z tego bloga

Kubernetes

Helm

Ansible Tower / AWX