Что значит шаблон?
при объявлении шаблона я привык иметь такой код:
template <class T>
но в этом вопросе, они использовали:
template <unsigned int N>
Я проверил, что он компилирует. Но что это значит? Это не тип параметра? И если да, то как мы можем иметь шаблон без какого-либо параметра типа?
4 ответов:
это вполне возможно, чтобы шаблон класса на целое число, а не тип. Мы можем присвоить шаблонное значение переменной или иным образом манипулировать им так, как мы могли бы с любым другим целочисленным литералом:
unsigned int x = N;фактически, мы можем создавать алгоритмы, которые оценивают во время компиляции (от Википедия):
template <int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; }; template <> struct Factorial<0> { enum { value = 1 }; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void foo() { int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1 }
Да, это не тип параметра. Вы можете иметь несколько видов параметров шаблона
- Параметры Типа.
- типы
- Шаблоны (только классы и шаблоны псевдонимов, никаких функций или шаблонов переменных)
- параметры не-типа
- указатели
- ссылки
- интегральные константные выражения
что у вас там из последнего рода. Это постоянная времени компиляции (так называемое константное выражение) и имеет тип integer или enumeration. После просмотра его в стандарте мне пришлось переместить шаблоны классов в раздел типы - даже если шаблоны не являются типами. Но они называются параметрами типа с целью описания этих видов, тем не менее. Вы можете иметь указатели( а также указатели на члены) и ссылки на объекты / функции, которые имеют внешнюю связь (те, которые могут быть связаны с другими объектные файлы и адрес которых уникален во всей программе). Примеры:
тип шаблона параметр:
template<typename T> struct Container { T t; }; // pass type "long" as argument. Container<long> test;целочисленный параметр шаблона:
template<unsigned int S> struct Vector { unsigned char bytes[S]; }; // pass 3 as argument. Vector<3> test;параметр указателя шаблона (передача указателя на функцию)
template<void (*F)()> struct FunctionWrapper { static void call_it() { F(); } }; // pass address of function do_it as argument. void do_it() { } FunctionWrapper<&do_it> test;параметр ссылки на шаблон (передача целого числа)
template<int &A> struct SillyExample { static void do_it() { A = 10; } }; // pass flag as argument int flag; SillyExample<flag> test;параметр шаблона шаблона.
template<template<typename T> class AllocatePolicy> struct Pool { 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) { return 0; } }; Pool<allocator> test;шаблон без параметров не представляется возможным. Но шаблон без каких-либо явный аргумент возможен - он имеет аргументы по умолчанию:
template<unsigned int SIZE = 3> struct Vector { unsigned char buffer[SIZE]; }; Vector<> test;синтаксически,
template<>зарезервировано для обозначения явной специализации шаблона, а не шаблона без параметров:template<> struct Vector<3> { // alternative definition for SIZE == 3 };
вы templatize вашего класса на основе 'беззнаковый инт'.
пример:
template <unsigned int N> class MyArray { 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. }
класс шаблона похож на макрос, только намного меньше зла.
думаю, что шаблона с макросом. Параметры шаблона подставляются в определение класса (или функции), когда вы определяете класс (или функцию) с помощью шаблона.
разница заключается в том, что параметры имеют "типы" и передаваемые значения проверяются во время компиляции, как параметры для функций. Допустимые типы-это обычные типы C++, такие как int и char. Когда вы создаете экземпляр a класс шаблона, вы передаете значение указанного типа, и в новой копии определения класса шаблона это значение подставляется туда, где имя параметра было в исходном определении. Прямо как макрос.
вы также можете использовать "
class" или "typename" типы параметров (они одинаковые). С параметром одного из этих типов можно передать имя типа вместо значения. Как и раньше, везде имя параметра было в классе шаблона определение, как только вы создаете новый экземпляр, будет ни пройти. Это наиболее распространенное использование для класса шаблонов; Все, кто знает что-либо о шаблонах C++, знают, как это сделать.рассмотрим этот шаблон класса пример кода:
#include <cstdio> template <int I> class foo { void print() { printf("%i", I); } }; int main() { foo<26> f; f.print(); return 0; }это функционально то же самое, что и этот макрос-с помощью кода:
#include <cstdio> #define MAKE_A_FOO(I) class foo_##I \ { \ void print() \ { \ printf("%i", I); \ } \ }; MAKE_A_FOO(26) int main() { foo_26 f; f.print(); return 0; }конечно, версия шаблона в миллиард раз безопаснее и гибче.
Comments