2013-03-25 3 views
3

클래스를 만들어 컨테이너가 std::array인지 확인합니다. 그러나 std::array에서 상속 한 컨테이너를 catch 할 수 없습니다. 모든 솔루션?SFINAE를 사용하여 상속 된 클래스를 기반으로 변형 할 수 없음

#include <vector> 
#include <array> 
#include <iostream> 

using namespace std; 

template<typename C> 
struct container_traits { constexpr static bool is_array = false; }; 
template<typename T, size_t S> 
struct container_traits<std::array<T,S>> { constexpr static bool is_array = true; }; 

template<typename T, size_t S> 
struct A : public std::array<T,S> {}; 

int main() 
{ 
    cout << container_traits<A<int, 5>>::is_array << endl;    // must return 1 
    cout << container_traits<std::array<int, 10>>::is_array << endl; // must return 1 
    cout << container_traits<std::vector<int>>::is_array << endl;  // must return 0 
    return 0; 
} 
+0

__is_base_of type_traits가있는 enable_if를 사용해 보셨습니까? – Alon

+6

@ Alon : 이중 밑줄을 사용하지 마십시오! 그것들은 구현 세부 사항입니다. 대신'std :: is_base_of'를 사용하십시오. – Xeo

+1

상속 또는 템플릿? 하나를 선택. –

답변

7

당신은 std::is_base_of을 사용할 수

template <typename C> 
struct container_traits { 
    constexpr static bool is_array = false; 
}; 

template <template <typename, std::size_t> class C, 
      typename T, std::size_t N> 
struct container_traits<C<T,N>> { 
    constexpr static bool is_array = std::is_base_of<std::array<T,N>, C<T,N>>::value; 
}; 

See it in action을.

기본적으로 두 가지 매개 변수를 사용하는 모든 템플릿 유형에 특화되어 있습니다. 그리고 해당 전문 분야에서 is_array의 값은 std::is_base_of에 의해 결정됩니다.

+1

공개/비공개 상속 문제를 피하는 is_base_of에 +1. –

6

작성자 주 :이 솔루션에 투표하지 마십시오. sftrabbit이 내 것보다 낫기 때문에 대신 투표하십시오. 비록 결함이 있긴하지만 일부 사람들은 그 아이디어가 흥미 롭기 때문에 나는 삭제하지 않을 것입니다. 그렇지 않으면 코드를

그것은 std::array<T, N>에서 파생되는 클래스에 대한 것을 언급 할 가치가있다 (예를 들어 A) 상속이 public이어야합니다 :

template<typename C> 
struct container_traits { 

private: 

    template <typename T, size_t N> 
    static char (&is_array_helper(const std::array<T, N>&))[1]; 

    static char (&is_array_helper(...))[2]; 

public: 

    constexpr static bool is_array = 
     sizeof(is_array_helper(std::declval<C>())) == sizeof(char[1]); 

}; 

을 :

당신이 원하는 결과를 제공 컴파일되지 않습니다. 이 문제를 해결하려면 std::is_base_of을 사용하거나 일부 SFINAE 기술을 적용 할 수 있습니다. 그러나 접근성과 관련된 SFINAE 규칙이 C++ 03에서 C++ 11로 변경되었으며 얼마 전 테스트 한 결과 일부 주요 컴파일러는 새 규칙을 구현하지 않았습니다. 그들이 지금 할 수 있습니다.

필자는 더 나은 솔루션이 나오는지 기다리는 질문 작성자에게 제안합니다.

+0

@Alon은 설명 할 부분이 많습니까? 함수 오버로드를 기반으로하는 아주 기본적인 SFINAE입니다. – Yakk

+1

글쎄, 전에는 그렇게 해본 적이 없었습니다. 흥미로운 솔루션. –

+0

@sftrabbit : 잘 모르겠지만 원래의 아이디어 (과부하 및 반환 유형의 크기 확인)가 Andrei Alexandrescu 's입니다. –

관련 문제