2011-03-10 9 views
3

nontype (int 변수) 템플릿 매개 변수에 문제가 있습니다.
함수에 상수 int 변수를 전달하고 함수가 템플릿을 인스턴스화하도록 허용 할 수없는 이유는 무엇입니까?Nontype 템플릿 매개 변수

template<int size> 
class MyTemplate 
{ 
    // do something with size 
}; 

void run(const int j) 
{ 
    MyTemplate<j> b; // not fine 
} 
void main() 
{ 
    const int i = 3; 
    MyTemplate<i> a; // fine; 
    run(i); // not fine 
} 

잘하지 : 컴파일러는 말한다, 오류 : 'j는'이것은 내가 함께 결국 무엇

  • 편집

상수 표현에 나타날 수 없습니다. 어쩌면 누군가 그것을 사용할 수도 있고 누군가 더 좋은 방법을 제안 할 수도 있습니다.

enum PRE_SIZE 
{ 
    PRE_SIZE_256 = 256, 
    PRE_SIZE_512 = 512, 
    PRE_SIZE_1024 = 1024, 
}; 

template<int size> 
    class SizedPool : public Singleton< SizedPool<size> > 
{ 
public: 
    SizedPool() 
     : mPool(size) 
    { 
    } 
    void* Malloc() 
    { 
     return mPool.malloc(); 
    } 

    void Free(void* memoryPtr) 
    { 
     mPool.free(memoryPtr); 
    } 

private: 
    boost::pool<>  mPool; 
}; 

template<int size> 
    void* SizedPoolMalloc() 
    { 
     return SizedPool<size>::GetInstance()->Malloc(); 
    } 

template<int size> 
    void SizedPoolFree(void* memoryPtr) 
    { 
     SizedPool<size>::GetInstance()->Free(memoryPtr); 
    } 

void* SizedPoolMalloc(int size) 
{ 
    if (size <= PRE_SIZE_256) 
     return SizedPoolMalloc<PRE_SIZE_256>(); 
    else if (size <= PRE_SIZE_512) 
     return SizedPoolMalloc<PRE_SIZE_512>(); 
} 


void toRun(const int j) 
{ 
    SizedPoolMalloc(j); 
} 
void Test17() 
{ 
    const int i = 3; 
    toRun(i); 
} 
+0

+1 좋은 질문입니다! – Nawaz

+0

잠깐. 템플릿 인수는 컴파일 타임에 컴파일러가 알아야하기 때문입니다. –

답변

9

비 형식 템플릿 매개 변수는 컴파일시 값을 필요로하기 때문에. 템플릿은 컴파일 타임 메커니즘이라는 것을 기억하십시오. 템플릿은 최종 실행 파일에 존재하지 않습니다. 또한 함수와 함수에 인수를 전달하는 것이 런타임 메커니즘이라는 것을 기억하십시오. run()에있는 j 매개 변수의 값은 실제로 프로그램이 실행되고 run() 함수를 호출 할 때까지 알 수 없습니다. 컴파일 단계 이후에 실행됩니다. 컴파일러가 불평 이유

void run(const int j) 
{ 
    // The compiler can't know what j is until the program actually runs! 
    MyTemplate<j> b; 
} 

const int i = 3; 
run(i); 

는 "상수 표현에 나타날 수 없습니다 'J'를"말했다.

한편, 컴파일시에 i의 값을 알고 있기 때문에 괜찮습니다.

const int i = 3; 
// The compiler knows i has the value 3 at this point, 
// so we can actually compile this. 
MyTemplate<i> a; 

컴파일 타임 값은 런타임 구조에 전달할 수 있지만 그 반대의 경우는 아닙니다. J는 컴파일시에 알려 져야하기 때문에

template<int j> 
void run() 
{ 
    MyTemplate<j> b; 
} 

const int i = 3; 
run<i>(); 
+0

음, 나는 컴파일 타임에 정의되어 run()에 전달하기 때문에 시간 상수가 컴파일 될 것이라고 생각했다. 이 문제가 해결 되었습니까?(공통 요구 사항으로 보임) – eugene

+0

@Eugene : 함수를 호출하고 함수에 인수를 전달하는 것은 런타임 메커니즘입니다. 'run()'의 함수 본문은 실제로'j'가 실제로 컴파일 타임 상수라는 것을 알 수 없습니다. 'run()'이 완전히 다른 소스 파일에 정의 되었다면 어떨까요? 다른 도서관이나 응용 프로그램에서? –

+0

와우 나는 방금 제안한 것을했다. (더미 클래스에서도 클래스 밖에서 템플릿 함수를 정의 할 수 있다는 것을 몰랐다.) – eugene

1

:

그러나, 당신은 당신의 run() 기능은 비 형 템플릿 매개 변수를 귀하의 MyTemplate 템플릿 클래스가 아닌 형태의 템플릿 매개 변수를 받아 같은 방법을 받아 들일 수 있습니다. 귀하의 예에서는 그렇지 않습니다.

const int a = 5; 
MyTemplate<a> foo; // OK 

const int b = rand(); 
MyTemplate<b> foo; // Not OK. 

첫번째 예는 컴파일 시간 상수 :

+1

매우 고상한 답변. +1 – Nawaz

2

기본적 C++ 상수 두 종류가있다. C++ 표준에서 말하는 ICE (Integral Constant Expression)입니다. 두 번째 예제는 런타임 상수입니다. 그것은 같은 C++ 타입 (const int)이지만 ICE는 아닙니다.

함수 void run(const int j)은 런타임 상수입니다. 사용자 입력을 전달할 수도 있습니다. 따라서 유효한 템플릿 인수가 아닙니다.

컴파일러는 템플릿 인수 값을 기반으로 코드를 생성해야한다는 규칙이 적용됩니다. 컴파일 타임 상수가 없다면 그렇게 할 수 없습니다.

관련 문제