2014-07-08 2 views
2

std :: enable_if를 사용하여 다양한 유형의 함수를 특수화하려고합니다.
여기 내가 수행하려고하는 것의 더 단순한 버전이 있습니다. 컴파일 할 때std :: enable_if 사용

#include <type_traits> 
#include <string> 

struct Ip 
{}; 

template <typename T> 
bool Equal(const std::string& s, const T& data) 
{return s == data;} 

template <typename T> 
bool Equal(const std::string& s, const typename std::enable_if<std::is_integral<T>::value, T>::type& data) 
{ 
    //int specific 
} 

template <typename T> 
bool Equal(const std::string& s, const typename std::enable_if<std::is_floating_point<T>::value, T>::type& data) 
{ 
    //Float specific 
} 

//Specialization 
template <> bool Equal(const std::string& s, const Ip& data) 
{ 
    //Ip specific 
} 

int main() 
{ 
    //Equal("21",21); // Do not compile 
    Equal("21","42.5"); // Compile 
} 

하지만, 표준 : enable_if와 템플릿 기능은 해상도에 참여하지 않는 것, 그래서 컴파일러는 내 함수 호출을 일치하는 기능이 없다는 것을 알려줍니다. 반환 유형으로 std::enable_if을 사용해 보았지만 거기에는 행운이 없습니다. 나는이 코드에서 내가 몹시 잘못하고있는 일이있을 것이라고 확신한다. 그렇지 않으면 잘못된 방향으로 시도하려고한다.
나는 모든 int 특성화 (int, short, long, long long, ...)를 쓰려고하지 않으므로 누구나이 솔루션을 사용할 수 있습니까?

+0

//Overload bool Equal(const std::string& s, const Ip& data) { //Ip specific return false; } 

는 생각 http://www.gotw.ca/publications/mill17.htm – Slava

+0

@Slava : 그는 템플릿을 사용하려고 시도하지 않는 것 전문화. –

+0

@Slava : 마지막 경우에 대한 좋은 링크 ('Ip'에 대한 전문화), 그러나 다른 경우에는 다른 문제가 있습니다. – Jarod42

답변

4

코드에 몇 가지 변경을 가할 수 있는데, 제약없는 기능 템플릿부터 시작합니다. 별도로 산술 유형을 처리하므로 T이 정수 또는 부동 소수점이 아닌 경우에만 선택해야합니다.

template <typename T> 
typename std::enable_if<!std::is_integral<T>::value && 
         !std::is_floating_point<T>::value, bool>::type 
    Equal(const std::string& s, const T& data) 
{return s == data;} 

이제 방법은 통합 및 부동 소수점 유형에 대한 Equal을 정의한 비 추론 문맥이기 위하여 T됩니다. enable_if을 더미 템플릿 매개 변수로 이동하여 공제 할 수 있습니다 (위와 같이 반환 유형을 사용할 수도 있음).

template <typename T, 
      typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr> 
bool Equal(const std::string& s, const T& data) 
{ 
    //int specific 
    return false; 
} 

template <typename T, 
      typename std::enable_if<std::is_floating_point<T>::value, T>::type* = nullptr> 
bool Equal(const std::string& s, const T& data) 
{ 
    //Float specific 
    return false; 
} 

마지막으로 Ip 처리를 전문으로하지 않아도 과부하를 생성 할 수 있습니다. 그것이 여기에서 설명 작동하지 않는 이유 Live demo

+0

감사합니다. 좋은 답변이지만 시각적 인 2012로되어 있으며 기본 템플릿 인수를 사용할 수 없습니다. 대신 반환 형식에서 std :: enable_if 사용하고 작동합니다. 둘 사이에 차이점이 있습니까? – Kiroxas

+0

@Kiroxas 제 생각에는 템플릿 매개 변수에이 매개 변수를 사용하면 함수 서명을 더 쉽게 읽을 수 있습니다. 하지만 그렇지 않으면 기능상의 차이가 없습니다. – Praetorian

3

다음 작품 : (https://ideone.com/G1vJKm) 귀하의 경우에는

#include <string> 
#include <type_traits> 

struct Ip 
{ 
    std::string ip; 
}; 

template <typename T> 
typename std::enable_if<!std::is_integral<T>::value && !std::is_floating_point<T>::value, bool>::type 
Equal(const std::string& s, const T& data) 
{return s == data;} 

template <typename T> 
typename std::enable_if<std::is_integral<T>::value, bool>::type 
Equal(const std::string& s, const T& data) 
{ 
    //int specific 
    return false; 
} 

template <typename T> 
typename std::enable_if<std::is_floating_point<T>::value, bool>::type 
Equal(const std::string& s, const T& data) 
{ 
    //Float specific 
    return false; 
} 

bool Equal(const std::string& s, const Ip& data) 
{ 
    //Ip specific 
    return false; 
} 

,

template <typename T> 
bool Equal(const std::string& s, const T& data) 

는 통합 및 부동 소수점에 대한 또한, 모든 T에 대한 유효한 후보입니다.

다른 템플릿 함수는 컴파일러에서 typename std::enable_if<std::is_integral<T>::value, T>::type에 대해 T 유형을 추론 할 수 없습니다.

그리고 Ip 버전의 경우 간단한 오버로드로 충분합니다.

+0

감사합니다. 완벽하게 작동합니다. – Kiroxas

관련 문제