2012-09-27 6 views
9

enable_if 오류 : 내가 알고있는 것처럼C++ (11) 나 C++ 11 enable_if 다음과 같은 예를 보았다

struct is_64_bit 
{ 
    static const bool value = sizeof(void*) == 8; 
}; 

enable_if<is_64_bit::value, void>::type 
my_memcpy(void* target, const void* source, size_t n) 
{ 
    cout << "64 bit memcpy" << endl; 
} 

enable_if<!is_64_bit::value, void>::type 
my_memcpy(void* target, const void* source, size_t n) 
{ 
    cout << "32 bit memcpy" << endl; 
} 

, 시스템 아키텍처에 따라 "my_memcpy"기능 32 중 하나를 사용할 수를 또는 64 비트 버전. 하지만 컴파일시 다음과 같은 오류를 받고 있어요 :

error: ‘type’ in ‘struct std::enable_if<false, void>’ does not name a type 

나는 (I 리눅스 페도라 32 비트를 사용하고 있습니다)에만 32 버전을 사용할 수 있어야한다 생각했기 때문에 나는 조금 혼란 스러워요.

아마도이 예제에 문제가 있습니까? 또는 나는 무엇인가 놓치고 있냐?

감사합니다.

답변

9

template< bool B, class T = void > struct enable_if 템플릿은 조건 B가 true 인 경우에만 typedef type이되도록 특수화되어 있습니다.

컴파일러가 정확합니다. type에 대한 typedef는 struct std::enable_if<false, void>에 없습니다. struct std::enable_if<true, void>에는 typedef 만 있습니다.

자세한 내용은 here을 참조하십시오.

문제를 해결하려면 false으로 평가되는 B가있는 enable_if이 컴파일되지 않도록해야합니다. 의 도움을 받아 my_memcpy을 기능 템플릿으로 만들어이를 수행 할 수 있습니다. 컴파일러는 B가 false으로 평가되고 B가 true으로 평가되는 함수를 성공적으로 컴파일하고 사용하는 함수 템플릿을 컴파일하지 못하면 오류를보고하지 않습니다. 오류가 특정 유형의 함수 템플릿을 인스턴스화에서 발생할 때, 프로그램이 그 함수 템플릿 오버로드 확인에 참여하지 컴파일을 계속한다고 substitution failure is not an error의 원칙 (SFINAE)를 통해

#include <iostream> 
#include <type_traits> 

using namespace std; 


struct is_64_bit 
{ 
    static const bool value = sizeof(void*) == 8; 
}; 

template<typename T> 
typename enable_if<is_64_bit::value, T>::type 
my_memcpy(T* target, const T* source, size_t n) 
{ 
    cout << "64 bit memcpy" << endl; 
} 

template<typename T> 
typename enable_if<!is_64_bit::value, T>::type 
my_memcpy(T* target, const T* source, size_t n) 
{ 
    cout << "32 bit memcpy" << endl; 
} 
+0

감사 싸이언합니다. 이제 해결되었습니다. 또한이 주제에 대해 더 잘 이해하고 있습니다. :) – user1274605

10

std::enable_if 작품.

SFINAE를 실행하려면 (a) 함수 (또는 메서드) 템플릿에서 사용해야하며 (b) 템플릿 매개 변수에 종속되어야합니다. 귀하의 프로그램은 두 가지 모두에서 실패합니다.

템플릿 매개 변수에 enable_if 의존하려면, 가장 쉬운 것은 기본 매개 변수를 추가하는 것입니다

template<typename T = void> typename enable_if<is_64_bit::value, T>::type 
my_memcpy(void* target, const void* source, size_t n) 

그러나,이 enable_if의 일반 합리적인 사용하지 않을을; 인터셉터 컴파일 오류에 의존하기 때문에 값 비싼 경향이 있습니다. 템플릿 전문화는 훨씬 더 좋은 아이디어가됩니다.

#include <iostream> 

template<int = sizeof(void *)> void my_memcpy(void* target, const void* source, size_t n); 

template<> void my_memcpy<8>(void* target, const void* source, size_t n) { 
    std::cout << "64 bit memcpy" << std::endl; 
} 

template<> void my_memcpy<4>(void* target, const void* source, size_t n) { 
    std::cout << "32 bit memcpy" << std::endl; 
} 
+0

+1 "SFINAE를 시작하려면 (a) 함수 (또는 메소드) 템플릿에 사용해야하며 (b) 템플릿 매개 변수에 종속되어야합니다." 지금 나는 그것을 정말로 얻는다. – Claudiu

3

SFINAE는 템플릿 용입니다. 당신이 필요한 것은 다른 답변이 언급 한 바와 같이, 템플릿을 사용하는 것입니다, 아니면 그냥 IMO는 (오히려 불필요한 템플릿을 소개하는 것보다) 더 적합한 솔루션입니다 컴파일 타임 지점이 있습니다

struct is_64_bit : 
    std::integral_constant<bool, sizeof(void*) == 8> 
{}; 

namespace detail 
{ 
    void my_memcpy(void* target, const void* source, std::size_t n, std::true_type) 
    { 
     std::cout << "64 bit memcpy" << std::endl; 
    } 


    void my_memcpy(void* target, const void* source, std::size_t n, std::false_type) 
    { 
     std::cout << "32 bit memcpy" << std::endl; 
    } 
} 

void my_memcpy(void* target, const void* source, std::size_t n) 
{ 
    my_memcpy(target, source, n, is_64_bit()); 
}