Что значит шаблон?



при объявлении шаблона я привык иметь такой код:



template <class T>


но в этом вопросе, они использовали:



template <unsigned int N>


Я проверил, что он компилирует. Но что это значит? Это не тип параметра? И если да, то как мы можем иметь шаблон без какого-либо параметра типа?

563   4  

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

    Ничего не найдено.