• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Nietypowy kod z szablonami [C++]

Object Storage Arubacloud
0 głosów
289 wizyt
pytanie zadane 5 czerwca 2019 w C i C++ przez profesorek96 Szeryf (91,420 p.)

Witam was.

Ostatnio natrafiłem w sieci na taki kod. Nie bardzo go rozumiem jak działa ? Czy znalazł by się ktoś kto wytłumaczył by co właściwie się w nim dzieje?

#include <iostream>
using namespace std;

template<typename... T> struct varSzabl{};
template<typename T, typename... Rest>

struct varSzabl<T, Rest...> : varSzabl<Rest...> {
	varSzabl(T typB, Rest... rest):
		varSzabl<Rest...>(rest...), obTypuBiez(typB) {
		cout << obTypuBiez << " ";
	}
	T obTypuBiez;
};
int main()
{
	varSzabl<int, double> iD(1., 2.);

	//wypisuje 2,1

	system("pause");
}

 

komentarz 5 czerwca 2019 przez tkz Nałogowiec (42,000 p.)
komentarz 5 czerwca 2019 przez vector Dyskutant (9,200 p.)
To nie jest fold expressions. fold expressions jest od c++17, a ten kod poprawnie się kompiluje pod standardem c++11.

1 odpowiedź

+4 głosów
odpowiedź 5 czerwca 2019 przez vector Dyskutant (9,200 p.)
edycja 7 czerwca 2019 przez vector
 
Najlepsza
template<typename... T> struct varSzabl{};

To jest deklaracja szablonu struktury z jedną paczką parametrów.
Paczka parametrów jest to parametrem szablonu który akceptuje 0 lub więcej parametrów szablonowych wliczając w to typy, nie typy oraz inne szablony.

template<typename T, typename... Rest>
struct varSzabl<T, Rest...> : varSzabl<Rest...> {
  // ...
};

To jest deklaracja specjalizacji szablonu.
Podczas dedukcji parametrów szablonu standard precyzuje że specjalizacje powinny być brane pod uwagę z większym priorytetem, czyli jeżeli są możliwe dopasowania do podstawowego szablonu i specjalizacji szablonu to zostanie wybrana specjalizacja szablonu.
typ varSzabl<T, Rest...> dziedziczy po typie varSzabl<Rest...>. Gdy uruchamiany jest konsturktor danego typu to wcześniej przed wykonaniem jego kodu uruchamiane są wszystkie konsturktor klas bazowych przez co wypisuje 2, 1 a nie 1, 2.

 

deklarując zmienną w maine 

varSzabl<int, double> iD(1., 2.);

następują takie dedukcje

// użyta zostaje specjalizacja
template<T = int, Rest= [double] >
struct varSzabl<int, double> : varSzabl<double> /* <- (1) */ {
 // ...
};

// użyta zostaje specjalizacja
template<T = double, Rest = []>
struct varSzabl<double> /* <- (1) */ : varSzabl<> /* <- (2) */ {
  // ...
};

// użyta zostaje podstawowa definicja
template<T = []>
struct varSzabl /* <- (2) */ {};

ten kod jest koncepcyjnie równoważny z takim kodem bez szablonów

#include <iostream>
using namespace std;

struct Szbl {};

struct SzblDouble : Szbl {
    SzblDouble(double typb) : Szbl(), obTypuBiez(typb) {
        std::cout << obTypuBiez << " ";
    }
    double obTypuBiez;
};

struct SzblIntDouble : SzblDouble {
    SzblIntDouble(int typb, double rest) : SzblDouble(rest), obTypuBiez(typb) {
        std::cout << obTypuBiez << " ";
    }
    double obTypuBiez;
};

int main() {
    SzblIntDouble szbl(1., 2.);
    system("pause");
}

Możesz sobie doczytać o szablonach tutaj, i paczkach parametrów tutaj.

// Edit

Bardzo polecam stronę https://cppinsights.io/ pozwala zobaczyć dokładniej co kompilator robi z kodem. Tutaj masz odnośnik z twoim kodem.

komentarz 8 czerwca 2019 przez Jakub 0 Pasjonat (23,120 p.)

@vector

Witam, jeszcze ja mam drobne pytanie w tym temacie. Nie rozumiem tylko tego fragmentu kodu:

: varSzabl<Rest...>(rest...), 

o ile się nie mylę jest to inicjalizacja obiektu klasy/struktury bazowej. Przekazywany jest do jej konstruktora rozpakowany pakiet, ale do jakiego konstruktora?!

Przecież deklaracja szablonu wygląda tak:

template<typename... T> struct varSzabl{};

tak więc nie wiem co się dzieje w tej linijce...

będę bardzo wdzięczny za wytłumaczenie tego miejsca i pozdrawiam ;)

1
komentarz 8 czerwca 2019 przez vector Dyskutant (9,200 p.)

W przypadku gdy Rest jest niepustą paczką zostaje użyta specjalizacja jako klasa bazowa

template<typename T, typename... Rest>
struct varSzabl<T, Rest...> : varSzabl<Rest...> {
    varSzabl(T typB, Rest... rest):
        varSzabl<Rest...>(rest...), obTypuBiez(typB) {
        cout << obTypuBiez << " ";
    }
    T obTypuBiez;
};

W przeciwnym przypadku zostanie użyta klasa podstawowa jako bazowa

komentarz 8 czerwca 2019 przez Jakub 0 Pasjonat (23,120 p.)
A nie na odwrót? Tzn, kiedy Rest... jest paczką pustą to zastanie wybrana klasa bazowa a w przeciwnym razie pochodna ( czyli specjalizacja <T, Rest...> ). Dobrze myślę?

* bo chyba to miałeś na myśli tyle że źle zrozumiałem.

Podobne pytania

0 głosów
1 odpowiedź 142 wizyt
pytanie zadane 3 września 2019 w C i C++ przez enigmatycznyclay Bywalec (2,450 p.)
+1 głos
2 odpowiedzi 491 wizyt
pytanie zadane 21 sierpnia 2018 w C i C++ przez draghan VIP (106,230 p.)
0 głosów
1 odpowiedź 152 wizyt
pytanie zadane 7 lutego 2021 w PHP przez CSSoup Mądrala (6,460 p.)

92,573 zapytań

141,423 odpowiedzi

319,648 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...