Jest całkowicie możliwe utworzenie szablonu klasy na podstawie liczby całkowitej zamiast typu. Możemy przypisać wartość szablonu do zmiennej lub w inny sposób manipulować nią w sposób, w jaki moglibyśmy to zrobić z dowolnym innym literałem całkowitoliczbowym:
unsignedint x = N;
W rzeczywistości możemy stworzyć algorytmy, które oceniają w czasie kompilacji (z Wikipedii ):
template<int N>structFactorial{enum{ value = N *Factorial<N -1>::value };};template<>structFactorial<0>{enum{ value =1};};// Factorial<4>::value == 24// Factorial<0>::value == 1void foo(){int x =Factorial<4>::value;// == 24int y =Factorial<0>::value;// == 1}
Możesz także użyć type static constexpr intzamiast swojego enum. Tak więc Factorial<0>szablon miałby static constexpr int value = 1i template <int N> struct Factorialmoże miećstatic constexpr int value = N * Factorial<N - 1>::value;
bobobobo
@bobobobo odpowiedź na to pytanie pojawiła się przed C ++ 11 i constexpr.
Justin Meiners,
154
Tak, jest to parametr inny niż typ. Możesz mieć kilka rodzajów parametrów szablonu
Parametry typu.
Rodzaje
Szablony (tylko szablony klas i aliasów, bez funkcji i szablonów zmiennych)
Parametry inne niż typowe
Wskaźniki
Bibliografia
Wyrażenia stałe całkowe
To, co tam masz, jest ostatniego rodzaju. Jest to stała czasowa kompilacji (tak zwane wyrażenie stałe) i jest typu integer lub enumeration. Po sprawdzeniu tego w standardzie musiałem przenieść szablony klas w górę do sekcji typów - mimo że szablony nie są typami. Niemniej jednak w celu opisania tych rodzajów nazywa się je parametrami typu. Możesz mieć wskaźniki (a także wskaźniki składowe) i odniesienia do obiektów / funkcji, które mają zewnętrzne powiązania (te, do których można dowiązać z innych plików obiektowych i których adres jest unikalny w całym programie). Przykłady:
Parametr typu szablonu:
template<typename T>structContainer{
T t;};// pass type "long" as argument.Container<long> test;
Parametr liczby całkowitej szablonu:
template<unsignedint S>structVector{unsignedchar bytes[S];};// pass 3 as argument.Vector<3> test;
Parametr wskaźnika szablonu (przekazywanie wskaźnika do funkcji)
template<void(*F)()>structFunctionWrapper{staticvoid call_it(){ F();}};// pass address of function do_it as argument.void do_it(){}FunctionWrapper<&do_it> test;
Parametr odwołania do szablonu (przekazywanie liczby całkowitej)
template<int&A>structSillyExample{staticvoid do_it(){ A =10;}};// pass flag as argumentint flag;SillyExample<flag> test;
Parametr szablonu szablonu.
template<template<typename T>classAllocatePolicy>structPool{void allocate(size_t n){int*p =AllocatePolicy<int>::allocate(n);}};// pass the template "allocator" as argument. template<typename T>struct allocator {static T * allocate(size_t n){return0;}};Pool<allocator> test;
Szablon bez parametrów nie jest możliwy. Ale szablon bez żadnego jawnego argumentu jest możliwy - ma domyślne argumenty:
Johannes, czy szablony są umieszczane w „typach”? Myślałem, że z jakich typów można zrobić, ale nie z samych typów?
sbi
@sbi zobacz wyjaśnienie: „Po sprawdzeniu tego w standardzie musiałem przenieść szablony klas w górę do sekcji typów - mimo że szablony nie są typami. Jednak w celu opisania tych rodzajów nazywa się je parametrami typu. ”. Tak mówi przypis 126 na 14.1 / 2. Jest to po prostu klasyfikacja, która ma na celu uczynienie parametrów innych niż typ czymś, co deklaruje wartość / odwołanie, a parametry typu są czymś, co deklaruje nazwę typu lub nazwę szablonu.
Johannes Schaub - litb
@ JohannesSchaub-litb, więc nie ma możliwości wpisania szablonu z, powiedzmy, std :: string? na przykład klasa template <std :: string S> z jakimś statycznym licznikiem w celu stworzenia unikalnego identyfikatora dla każdego innego ciągu? haszowanie łańcucha do int byłoby niestety jedynym sposobem, prawda?
relaxxx
1
Bardzo chciałbym, aby ta odpowiedź była zakończona obiektami składowymi klasy szablonu, tj. Szablon <nazwa typu C, nazwa typu R, nazwa typu P1, nazwa typu P2> struct mystruct <R (C :: *) (P1, P2)>
Johnny Pauling
Fragment kodu z SillyExamplenie może zostać skompilowany przez GCC 4.8.4. Pierwszy błąd to the value of ‘flag’ is not usable in a constant expression. Są też inne błędy
HEKTO
17
Tworzysz szablon swojej klasy na podstawie „unsigned int”.
Przykład:
template<unsignedint N>classMyArray{public:private:double data[N];// Use N as the size of the array};int main(){MyArray<2> a1;MyArray<2> a2;MyArray<4> b1;
a1 = a2;// OK The arrays are the same size.
a1 = b1;// FAIL because the size of the array is part of the// template and thus the type, a1 and b1 are different types.// Thus this is a COMPILE time failure.}
Klasa szablonów jest jak makro, tylko dużo mniej zła.
Pomyśl o szablonie jak o makrze. Parametry szablonu są podstawiane do definicji klasy (lub funkcji), kiedy definiujesz klasę (lub funkcję) za pomocą szablonu.
Różnica polega na tym, że parametry mają „typy”, a przekazywane wartości są sprawdzane podczas kompilacji, podobnie jak parametry do funkcji. Prawidłowe typy to zwykłe typy w C ++, takie jak int i char. Tworząc instancję klasy szablonu, przekazujesz wartość określonego typu, aw nowej kopii definicji klasy szablonu ta wartość jest zastępowana w miejscu, w którym nazwa parametru występowała w oryginalnej definicji. Podobnie jak makro.
Możesz także użyć typów „ class” lub „ typename” jako parametrów (są one naprawdę takie same). W przypadku parametru jednego z tych typów można przekazać nazwę typu zamiast wartości. Tak jak poprzednio, wszędzie, gdzie nazwa parametru znajdowała się w definicji klasy szablonu, gdy tylko utworzysz nową instancję, stanie się dowolnym przekazanym typem. Jest to najczęstsze zastosowanie klasy szablonów; Każdy, kto wie cokolwiek o szablonach C ++, wie, jak to zrobić.
static constexpr int
zamiast swojegoenum
. Tak więcFactorial<0>
szablon miałbystatic constexpr int value = 1
itemplate <int N> struct Factorial
może miećstatic constexpr int value = N * Factorial<N - 1>::value;
constexpr
.Tak, jest to parametr inny niż typ. Możesz mieć kilka rodzajów parametrów szablonu
To, co tam masz, jest ostatniego rodzaju. Jest to stała czasowa kompilacji (tak zwane wyrażenie stałe) i jest typu integer lub enumeration. Po sprawdzeniu tego w standardzie musiałem przenieść szablony klas w górę do sekcji typów - mimo że szablony nie są typami. Niemniej jednak w celu opisania tych rodzajów nazywa się je parametrami typu. Możesz mieć wskaźniki (a także wskaźniki składowe) i odniesienia do obiektów / funkcji, które mają zewnętrzne powiązania (te, do których można dowiązać z innych plików obiektowych i których adres jest unikalny w całym programie). Przykłady:
Parametr typu szablonu:
Parametr liczby całkowitej szablonu:
Parametr wskaźnika szablonu (przekazywanie wskaźnika do funkcji)
Parametr odwołania do szablonu (przekazywanie liczby całkowitej)
Parametr szablonu szablonu.
Szablon bez parametrów nie jest możliwy. Ale szablon bez żadnego jawnego argumentu jest możliwy - ma domyślne argumenty:
Składniowo,
template<>
jest zarezerwowany do oznaczania wyraźnej specjalizacji szablonu, zamiast szablonu bez parametrów:źródło
SillyExample
nie może zostać skompilowany przez GCC 4.8.4. Pierwszy błąd tothe value of ‘flag’ is not usable in a constant expression
. Są też inne błędyTworzysz szablon swojej klasy na podstawie „unsigned int”.
Przykład:
źródło
Klasa szablonów jest jak makro, tylko dużo mniej zła.
Pomyśl o szablonie jak o makrze. Parametry szablonu są podstawiane do definicji klasy (lub funkcji), kiedy definiujesz klasę (lub funkcję) za pomocą szablonu.
Różnica polega na tym, że parametry mają „typy”, a przekazywane wartości są sprawdzane podczas kompilacji, podobnie jak parametry do funkcji. Prawidłowe typy to zwykłe typy w C ++, takie jak int i char. Tworząc instancję klasy szablonu, przekazujesz wartość określonego typu, aw nowej kopii definicji klasy szablonu ta wartość jest zastępowana w miejscu, w którym nazwa parametru występowała w oryginalnej definicji. Podobnie jak makro.
Możesz także użyć typów „
class
” lub „typename
” jako parametrów (są one naprawdę takie same). W przypadku parametru jednego z tych typów można przekazać nazwę typu zamiast wartości. Tak jak poprzednio, wszędzie, gdzie nazwa parametru znajdowała się w definicji klasy szablonu, gdy tylko utworzysz nową instancję, stanie się dowolnym przekazanym typem. Jest to najczęstsze zastosowanie klasy szablonów; Każdy, kto wie cokolwiek o szablonach C ++, wie, jak to zrobić.Rozważ ten przykładowy kod klasy szablonu:
Funkcjonalnie jest taki sam jak ten kod wykorzystujący makra:
Oczywiście wersja szablonu jest miliard razy bezpieczniejsza i bardziej elastyczna.
źródło