2010-04-11 2 views
4

다음 코드의 함수 템플릿은 클래스 템플릿의 멤버이므로 둘러싸는 클래스를 전문화하지 않으면 특수화 할 수 없습니다.이 기능 템플릿을 완벽하게 모방 한 것입니까?

그러나 컴파일러의 전체 최적화가 설정된 경우 (Visual Studio 2010 가정) 다음 코드의 if-else-statement가 최적화됩니까? 그리고 만약 그렇다면, 모든 실제적인 목적을 위해 이것은 성능 비용없이 기능 템플릿 전문화라는 것을 의미하지 않을까요?

template<typename T> 
struct Holder 
{ 
    T data; 

    template<int Number> 
    void saveReciprocalOf(); 
}; 

template<typename T> 
template<int Number> 
void Holder<T>::saveReciprocalOf() 
{ 
    //Will this if-else-statement get completely optimized out 
    if(Number == 0)  data = (T)0; 
    else    data = (T)1/Number; 
} 

//----------------------------------- 
void main() 
{ 
    Holder<float> holder; 
    holder.saveReciprocalOf<2>(); 
    cout << holder.data << endl; 
} 

답변

3

최적화 될 가능성이 있습니다. 그러나 이 되려면을 사용하십시오. 예를 들어 템플릿을 사용하여 if의 컴파일 타임을 사용할 수 있습니다. Boost의 MPL if_ 구현.

또는 SFINAE (Boost.enable_if)를 사용할 수 있습니다. 이러한 문제를 해결하기

1

보통 방법은 아주 잘

template<typename T> 
struct Outer { 
    template<int I> 
    void inner() { 
    inner(int_<I>()); 
    } 

private: 
    template<int I> 
    struct int_ { }; 

    void inner(int_<0>) { 
    // for I == 0 
    } 

    template<int I> 
    void inner(int_<I>) { 
    // for others... 
    } 
}; 

이 모방 명시 적 전문 과부하를 통해, 다른 경로에 대한 유형 검사는 if 솔루션과는 달리 (미친 갈 것입니다 경우에도 경우에 작동 이 경로는 I != 0 경우 수행되기 때문에 작동)

// ... 
    template<int I> 
    void inner(int_<I>) { 
    int tmp[I]; 
    } 
// ... 

. 이제 귀하의 경우, 나는 왜 당신이 정상적인 함수 인수를 전달하지 않는지 궁금합니다. 이 필요하지 않습니다.의 컴파일 시간은 I입니다.

// works just fine too in your example 
template<typename T> 
void Holder<T>::saveReciprocalOf(int Number) 
{ 
    // Will this if-else-statement get completely optimized out 
    if(Number == 0)  data = (T)0; 
    else    data = (T)1/Number; 
} 

또한 컴파일러에서 함수 호출을 인라인하면 최적화될 가능성이 큽니다. 엄격히 필요하지 않은 템플릿 non-type 매개 변수를 사용하면 해당 함수의 기능이 런타임 값과 함께 작동하지 않을 수 있습니다.

+0

필자는 컴파일 된 변수가 컴파일 타임 상수 일 때 불필요한 조건부 블록을 최적화 할 가능성이 더 높다고 생각했습니다. 그러나 최적화가 정규 함수 인수를 사용할 때 일어날 가능성이 높다면, 거기에는 아무런 의미가 없다고 생각합니다. – zeroes00

+0

@ Zeroes00 먼저 성능에 영향을 미칠 수 있다고 생각하면 먼저 컴파일 한 다음 어셈블리를 확인하는 것이 좋습니다. 다음은 인상적인 최적화 컴파일러의 예입니다. http://stackoverflow.com/questions/2419650/cc-macro-template-blackmagic-to-generate-unique-name/2419715#2419715 –

0

감사합니다. 조건부가 최적화되어 있는지 확인하고 싶기 때문에 (아주 자주 내부 루프를 호출해야하고 루프 외부에 스위치 케이스를 사용하여 올바른 경로를 선택해야하기 때문에) 결국 enable_if_c 같은 것을 사용하게 될 것입니다. 다음 코드는

using boost::enable_if_c; 

template<typename T> 
struct Dummy 
{  
    template<int N> 
    typename enable_if_c<N==2,bool>::type    isPrimary() {return true;} 

    template<int N> 
    typename enable_if_c<N==3,bool>::type    isPrimary() {return true;} 

    template<int N> 
    typename enable_if_c<N==5,bool>::type    isPrimary() {return true;} 

    template<int N> 
    typename enable_if_c<N!=2&&N!=3&&N!=5,bool>::type isPrimary() {return false;} 
}; 

제게 이것은 요하네스의 제안보다 조금 복잡합니다. 마지막 (기본값) 경우는 꽤 추해 질 수 있습니다.

+0

전적으로 가능할 것으로 생각합니다. 값이 템플릿 메타 프로그래밍을 사용하는 소수라면 (적어도 일부 값까지 - 어쨌든 최대 6 개까지만 작동) 런타임 함수 호출이 전혀 없습니다. – UncleBens

+0

기본 번호 나 상호가 실제로 필요하지 않습니다. 클래스 템플릿 내에서 함수 템플릿을 특수화하는 방법을 파악하기위한 예제로 사용했습니다. – zeroes00

+0

'int_'는 마찬가지로'boost '를 통해 사용할 수 있습니다. 그것은'boost :: mpl :: int_'입니다. –

관련 문제