2017-12-22 18 views
2

클래스에 push의 두 가지 구현이 있고 부울 템플릿 인수를 기반으로 선택하겠습니다. 과 같이, this answer에 설명 된대로 나는 SFINAE 원리를 사용하여 시도 :부울 템플릿 매개 변수를 사용하여 멤버 함수를 사용하려면 어떻게해야하나요?

template<class T, bool foo=true> 
class Bar { 
    template <> 
    typename std::enable_if<foo>::type 
    push(const T& value) { /* one implementation */} 

    template <> 
    typename std::enable_if<!foo>::type 
    push(const T& value) { /* another implementation */ } 
} 

그러나, 나는 GCC에서 "클래스의 범위 내에서 함수 push을 전문으로 수 없습니다"의 오류를 얻고, 난 왜 이해가 안 돼요. 내 코드가 링크 된 답변의 코드와 정확히 같지는 않지만 매우 유사하며 중요한 차이점을 발견 할 수 없습니다.

는 또한 this answer에서 제안 된 것과 유사한 구문을 사용하여 시도하지만 그것도 작동하지 않습니다 (오류 대신 "클래스 멤버가 다시 선언 할 수 없다"입니다) :

template <bool enable=foo> 
    typename std::enable_if<enable>::type 
    push(const T& value) { /* one implementation */} 

    template <bool enable=!foo> 
    typename std::enable_if<enable>::type 
    push(const T& value) { /* another implementation */ } 

가 어떻게 이러한 목표를 달성 할 수 있습니까?

답변

2

첫째, SFINAE은 함수 템플릿 오버로드로 작동합니다. 그래서 두 번째 접근법을 따라 가야합니다. 그러나 동일한 서명으로 두 개의 오버로드를 선언합니다. 템플릿 매개 변수의 기본 인수는 서명에 속하지 않습니다. 대안으로

template <bool enable=foo> 
typename std::enable_if<enable>::type 
//      ~~~~~~ 
push(const T& value) { /* one implementation */} 

template <bool enable=foo> 
typename std::enable_if<!enable>::type 
//      ~~~~~~~ 
push(const T& value) { /* another implementation */ } 
+0

와우, 그건 완전히 작동합니다. 고맙습니다. –

2

변경을 :

  • if constexpr C++ 17 :

    template<class T, bool foo=true> 
    class Bar { 
    public: 
        void push(const T& value) { 
         if constexpr(foo) { 
          /* one implementation */ 
         } else { 
          /* another implementation */ 
         } 
        } 
    }; 
    
  • 태그 파견 :

    template<class T, bool foo=true> 
    class Bar { 
        void push_impl(const T& value, std::true_type) { 
         /* one implementation */ 
        } 
        void push_impl(const T& value, std::false_type) { 
         /* another implementation */ 
        } 
    
    public: 
        void push(const T& value) { 
         push_impl(value, std::integral_constant<bool, foo>{}); 
        } 
    }; 
    
+0

굉장합니다. 대체 옵션을 가져 주셔서 감사합니다. 나는이 점이 어느 시점에서 유용 할 것이라고 확신한다. –