1

나는 최근에 C++로 템플릿 메타 프로그래밍에 들어가고 있으며 몇 가지 기본 기능을 각각의 재귀 적 컴파일 타임 템플릿 정의로 변환하려고 시도해 왔습니다. 예를 들어C++에서 재귀 클래스 정의를 처리하는 방법은 무엇입니까?

:

template <typename T, T A, unsigned int N> 
class pow { enum : T { value = A * pow<T, A, N-1>::value } }; 
template <typename T, T A> class pow<T, A, 0> { enum : T { value = 1 } }; 

구문과 템플릿의 힘은 날 놀라게. 그러나 한 가지 질문은 나를 괴롭 히고 있습니다. C++에서 이러한 재귀 정의를 어떻게 처리합니까? 더 구체적으로 (현명한 자원)

또는 :

  • 컴파일러 (/ 방법 메모리가 할당) 열거 값을 포함하는 템플릿 클래스의 인스턴스 생성을 어떻게 처리합니까 어떻게

    ?

  • 생성 된 모든 클래스가 컴파일 후에 메모리에 남아 있습니까? 아니면 최상위 클래스 (정리) 만 유지하는 컴파일러에서 최적화되어 있습니까?

  • RAM에 독립적 인 최대 재귀 깊이가 있습니까? (컴파일러 자체의 제한 사항)?

이러한 구조의 표준 컴파일에 대한 자세한 설명은 매우 높이 평가할 수 있습니다.

+3

_ "최대 재귀 깊이가 있는가하는 ..."_ 경고 것 .org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html # C_002b_002b-Dialect-Options –

+0

그러면 currenrly 1024입니다. 그러나 그것은 컴파일러의 제약 조건인가 아니면 컨벤션인가? (이전의 C++ 표준에서는 17이 이상한 선택 이었기 때문에)? –

+1

컴파일러가 인스턴스화 된 유형을 덤프하는 것을 상상할 수 없습니다. 나중에 언젠가는 다시 사용할지 여부를 알 수있는 방법이 없습니다. 링크 단계에서 컬링 (culling)이 수행됩니다. 그리고 메타 프로그래밍을 통해 나는 도둑질이 완전해질 것으로 기대합니다. – SoronelHaetir

답변

1

pow::value은 컴파일 타임에 const express입니다. 컴파일러는 pow<T, A, N>::valueA * pow<T, A, N - 1>::value로 계산합니다. A는 또한 컴파일 시간에 const를 값이고, 컴파일러는 계산하기 위해 계속 pow<T, A, N - 1>::value

...

계산 pow<T, A, N - n>::value

계산 pow<T, A, N - n - 1>::value

... util을 중지

컴파일러 프로그램이 정의 했으므로 pow<T, A, 1>::value을 계산할 필요가 없습니다. pow<T, A, 1>::value = 1

,210

int main() { 
    int value = pow<int, 1, -1>::value; 
} 

GCC 컴파일러는 const를 값이 이전에 재귀 반복의 최대에 도달 찾을 could't 때문이다

fatal error: template instantiation depth exceeds maximum of xxx 

경고 것이다 작성하는 경우.

컴파일 후 컴파일러는 pow<T, A, N - n>::value의 값을 immediate number으로 유지하면서 중간 값을 유지하지 않습니다.

int main() { 
    400546:  55      push %rbp 
    400547:  48 89 e5    mov %rsp,%rbp 
    ... 
    int a = pow<int, 2, 8>::value; 
    40055d:  c7 45 f0 00 01 00 00 movl $0x100,-0x10(%rbp) 
    ... 
} 

$0x100pow<int, 2, 8>::value의 결과이다. 이 결과를 담고있는 추가 주소는 없습니다.

최대 재귀 깊이는 특수 컴파일러에 의해 결정됩니다.예를 들어, gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609 기본 최대 값은 900입니다. 프로그래머는이 값을 -ftemplate-depth까지 설정할 수 있습니다.

그러나 -ftemplate-depth 값은 최대 값 int32 (2147483647)을 초과 할 수 없습니다.

이 구조에서 재귀 깊이는 type T으로 제한 될 수도 있습니다. g의 ++는`-ftemplate-깊이 = 참조 n` : HTTPS : //gcc.gnu

int main() { 
    int result = pow<int, 2, 200>::value; 
} 

GCC는

error: overflow in constant expression [-fpermissive]