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

Nietypowy kod z szablonami [C++]

Cloud VPS
0 głosów
425 wizyt
pytanie zadane 5 czerwca 2019 w C i C++ przez profesorek96 Szeryf (91,400 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,060 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ź 203 wizyt
pytanie zadane 3 września 2019 w C i C++ przez enigmatycznyclay Bywalec (2,450 p.)
+1 głos
2 odpowiedzi 846 wizyt
pytanie zadane 21 sierpnia 2018 w C i C++ przez draghan VIP (106,230 p.)
0 głosów
1 odpowiedź 218 wizyt
pytanie zadane 7 lutego 2021 w PHP przez CSSoup Mądrala (6,460 p.)

93,454 zapytań

142,449 odpowiedzi

322,718 komentarzy

62,834 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

Kursy INF.02 i INF.03
...