sfinae를 사용하여 C ++ 유형의 포드 성을 감지합니다.
-
22-08-2019 - |
문제
여기의 원래 제목은였습니다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를 수행합니다.