문제

여기의 원래 제목은였습니다VS2005 C ++의 SFINAE 버그 해결 방법

이것은 TR1에 존재하는 IS_POD 템플릿 클래스에 동등한 것을 만들기 위해 sfinae의 잠정적 인 사용입니다 (VS2005에서 아직 TR1은 없습니다). 그것은 그것의 가져야합니다 템플릿 매개 변수가 POD 유형 (원시 유형 및 구조 포함) 일 때 멤버는 (사소한 생성자와 같이)가 아닌 경우 false입니다.

template <typename T> class is_pod
{
  public:

    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(int)
    {
      union {T validPodType;} u;
    }
    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(0)) == sizeof(Yes))};
};

class NonPOD
{
  public:
    NonPod(const NonPod &);
    virtual ~NonPOD();
};

int main()
{
  bool a = is_pod<char>::value;
  bool b = is_pod<NonPOD>::value;
  if (a) 
    printf("char is POD\n");
  if (b)
    printf("NonPOD is POD ?!?!?\n");
  return 0;
}

문제는 2005 년대로 TR1이 없을뿐만 아니라 위의 연합에 신경 쓰지 않을 것입니다 (템플릿 매개 변수가 POD가 아닌 경우에 유효하지 않아야 함) A와 B는 모두 true로 평가됩니다.


아래에 게시 된 답변에 감사드립니다. 조심스럽게 읽은 후 (그리고 코드) 나는 내가하려는 것이 실제로 잘못된 접근법이라는 것을 깨달았습니다. 아이디어는 sfinae 행동을 템플릿에 적응하는 것과 결합하는 것이 었습니다. must_be_pod (내가 책에서 찾은 것 불완전한 C ++, 그러나 다른 곳에서도 찾을 수 있습니다). 실제로 이것은 표준이 정의하는 것이 아니라 Sfinae에 대한 매우 특정한 규칙 세트가 필요합니다. 이것은 결국 VS의 버그가 아닙니다.

도움이 되었습니까?

해결책

접근 방식의 가장 큰 문제는 여기에서 sfinae를 수행하지 않는다는 것입니다. Sfinae는 매개 변수 유형 및 리턴 유형에만 적용됩니다.

그러나 표준의 모든 Sfinae 상황 중에서 귀하의 상황에는 적용되지 않습니다. 그들은

  • 공허, 참조, 함수 또는 유효하지 않은 크기의 배열
  • 유형이 아닌 유형의 멤버
  • 참조 포인터, 참조 참조, void에 대한 참조
  • 비 클래스 유형의 구성원에 대한 포인터
  • 템플릿 값 매개 변수의 잘못된 변환
  • 유형 void의 인수가있는 함수 유형
  • const/휘발성 함수 유형

이것이 바로 부스트 문서에 다음과 같은 이유 일 것입니다.

컴파일러의 일부 (아직 지정되지 않은) 도움이 없다면 ISPOD는 클래스 나 구조물이 포드라고보고하지 않습니다. 아마도 최적이라면 항상 안전합니다. 현재 (2005 년 5 월) MWCW 9와 Visual C ++ 8 만 필요한 컴파일러 -_intrinsics가 있습니다.

다른 팁

이것은 vs2008에서도 작동하지 않지만 나는 당신도 그것을 알고 있다고 생각합니다. sfinae는 템플릿 매개 변수에 대한 템플릿 인수를 추론하기위한 것입니다. 다른 유형과 호환되지 않는 유형을 만들 수는 있지만 (예 : Unions가 비 POD를 사용할 수 없음) 유형의 생성자 성을 드러내는 유형의 유형을 실제로 추론 할 수는 없습니다.

실제로 VS 2008은 컴파일러 지원을 사용하여 특성을 구현합니다. std::tr1::type_traits.

나는 당신이 여기서 sfinae를하려는 방식에 대해 잘 모르겠습니다. is_pod<T>::test(...) 일치합니다 is_pod<T>::test(0) 도. 아마도 'int'대신 다른 유형을 사용하면 더 나은 일치를 얻을 수 있습니다.

template <typename T> class is_pod
{
  struct my_special_type { };
  public:
    typedef char Yes;
    typedef struct {char a[2];} No;

    template <typename C> static Yes test(my_special_type)
    {
      union {T validPodType;} u;
    }

    template <typename C> static No test(...)
    {
    }
    enum {value = (sizeof(test<T>(my_special_type())) == sizeof(Yes))};
};

당신은 또한보고 싶을 수도 있습니다 boost.enable_iF 자신의 도서관을 구현하거나 어떤 이유로 든 Sfinae를 수행합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top