<unsigned int N> 템플릿은 무엇을 의미합니까?


121

템플릿을 선언 할 때 다음과 같은 코드를 사용하는 데 익숙합니다.

template <class T>

그러나이 질문 에서 그들은 다음을 사용했습니다.

template <unsigned int N>

나는 그것이 컴파일되는지 확인했다. 그러나 그것은 무엇을 의미합니까? 유형이 아닌 매개 변수입니까? 그렇다면 유형 매개 변수가없는 템플릿을 어떻게 가질 수 있습니까?

답변:


148

유형이 아닌 정수로 클래스를 템플릿 화하는 것은 완벽하게 가능합니다. 템플릿 값을 변수에 할당하거나 다른 정수 리터럴을 사용하여 조작 할 수 있습니다.

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
}

11
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;
bobobobo

@bobobobo 이것은 C ++ 11 및 constexpr.
Justin Meiners 2016

154

예, 비 유형 매개 변수입니다. 여러 종류의 템플릿 매개 변수를 가질 수 있습니다.

  • 유형 매개 변수.
    • 종류
    • 템플릿 (클래스 및 별칭 템플릿 만, 함수 또는 변수 템플릿 없음)
  • 비 유형 매개 변수
    • 포인터
    • 참고 문헌
    • 정수 상수 표현식

당신이 가지고있는 것은 마지막 종류입니다. 컴파일 시간 상수 (소위 상수 표현식)이며 정수 또는 열거 유형입니다. 표준에서 찾아 본 후 템플릿이 유형이 아니더라도 클래스 템플릿을 유형 섹션으로 옮겨야했습니다. 그러나 그럼에도 불구하고 이러한 종류를 설명하기 위해 형식 매개 변수라고합니다. 포인터 (및 멤버 포인터) 및 외부 연결이있는 개체 / 함수에 대한 참조 (다른 개체 파일에서 연결될 수 있고 전체 프로그램에서 고유 한 주소)를 가질 수 있습니다. 예 :

템플릿 유형 매개 변수 :

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
};

요하네스, 템플릿은 "유형"아래에 정리되어 있습니까? 나는 그들이 어떤 유형으로 만들 수 있다고 생각했지만 유형 자체는 아니 었습니까?
sbi

@sbi는 설명을 참조하십시오. "표준에서 찾아 본 후 클래스 템플릿을 유형 섹션으로 옮겨야했습니다. 템플릿은 유형이 아니지만 그럼에도 불구하고 이러한 유형을 설명하기 위해 유형 매개 변수라고합니다. ". 14.1 / 2의 각주 126은 그렇게 말합니다. 그것은 값 / 참조를 선언하는 비 유형 매개 변수를 만들고 유형 매개 변수를 유형 이름 또는 템플릿 이름을 선언하는 어떤 것으로 만들기 위해 만들어진 분류 일뿐입니다.
Johannes Schaub-litb

@ JohannesSchaub-litb 그래서 std :: string이라고 말하면 템플릿을 입력하는 방법이 없습니까? 다른 모든 문자열에 대해 고유 한 ID를 생성하기 위해 정적 카운터가있는 template <std :: string S> 클래스처럼? 불행히도 문자열을 int로 해싱하는 것이 유일한 방법일까요?
relaxxx

1
이 답변이 템플릿 클래스 멤버 개체 (예 : template <typename C, typename R, typename P1, typename P2> struct mystruct <R (C :: *) (P1, P2)>)로 완료되는 것을보고 싶습니다.
Johnny Pauling

이있는 코드는 SillyExampleGCC 4.8.4로 컴파일 할 수 없습니다. 첫 번째 오류는 the value of ‘flag’ is not usable in a constant expression입니다. 다른 오류도 있습니다
HEKTO

17

'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.
 }

15

템플릿 클래스는 매크로와 같으며 훨씬 덜 사악합니다.

템플릿을 매크로로 생각하십시오. 템플릿을 사용하여 클래스 (또는 함수)를 정의하면 템플릿에 대한 매개 변수가 클래스 (또는 함수) 정의로 대체됩니다.

차이점은 매개 변수에 "유형"이 있고 전달 된 값이 함수에 대한 매개 변수처럼 컴파일 중에 확인된다는 것입니다. 유효한 유형은 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 억 배 더 안전하고 유연합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.