답변:
유형이 아닌 정수로 클래스를 템플릿 화하는 것은 완벽하게 가능합니다. 템플릿 값을 변수에 할당하거나 다른 정수 리터럴을 사용하여 조작 할 수 있습니다.
unsigned int x = N;
실제로 컴파일 타임에 평가하는 알고리즘을 만들 수 있습니다 ( Wikipedia에서 ).
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
}
constexpr
.
예, 비 유형 매개 변수입니다. 여러 종류의 템플릿 매개 변수를 가질 수 있습니다.
당신이 가지고있는 것은 마지막 종류입니다. 컴파일 시간 상수 (소위 상수 표현식)이며 정수 또는 열거 유형입니다. 표준에서 찾아 본 후 템플릿이 유형이 아니더라도 클래스 템플릿을 유형 섹션으로 옮겨야했습니다. 그러나 그럼에도 불구하고 이러한 종류를 설명하기 위해 형식 매개 변수라고합니다. 포인터 (및 멤버 포인터) 및 외부 연결이있는 개체 / 함수에 대한 참조 (다른 개체 파일에서 연결될 수 있고 전체 프로그램에서 고유 한 주소)를 가질 수 있습니다. 예 :
템플릿 유형 매개 변수 :
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
};
SillyExample
GCC 4.8.4로 컴파일 할 수 없습니다. 첫 번째 오류는 the value of ‘flag’ is not usable in a constant expression
입니다. 다른 오류도 있습니다
'unsigned int'를 기반으로 클래스를 템플릿 화합니다.
예:
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.
}
템플릿 클래스는 매크로와 같으며 훨씬 덜 사악합니다.
템플릿을 매크로로 생각하십시오. 템플릿을 사용하여 클래스 (또는 함수)를 정의하면 템플릿에 대한 매개 변수가 클래스 (또는 함수) 정의로 대체됩니다.
차이점은 매개 변수에 "유형"이 있고 전달 된 값이 함수에 대한 매개 변수처럼 컴파일 중에 확인된다는 것입니다. 유효한 유형은 int 및 char과 같은 일반 C ++ 유형입니다. 템플릿 클래스를 인스턴스화 할 때 지정한 유형의 값을 전달하고 템플릿 클래스 정의의 새 복사본에서이 값은 매개 변수 이름이 원래 정의에있을 때마다 대체됩니다. 마치 매크로처럼.
매개 변수에 " 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;
}
물론 템플릿 버전은 10 억 배 더 안전하고 유연합니다.
static constexpr int
대신 type을 사용할 수도 있습니다enum
. 너무Factorial<0>
템플릿은 것static constexpr int value = 1
, 그리고template <int N> struct Factorial
할 수 있습니다static constexpr int value = N * Factorial<N - 1>::value;