문제

대답 후 이것 내가 찾으려고했던 질문 is_complete Boost Library의 템플릿과 나는 Boost.typetraits에 그러한 템플릿이 없다는 것을 깨달았습니다. 부스트 라이브러리에 그러한 템플릿이없는 이유는 무엇입니까? 어떻게 생겼습니까?

//! Check whether type complete
template<typename T>
struct is_complete
{   
  static const bool value = ( sizeof(T) > 0 );
};

...

// so I could use it in such a way
BOOST_STATIC_ASSERT( boost::is_complete<T>::value );

위의 코드는 적용하는 것이 불법이기 때문에 정확하지 않습니다. sizeof 불완전한 유형으로. 좋은 해결책은 무엇입니까? 이 경우 Sfinae를 적용 할 수 있습니까?


글쎄,이 문제는 ODR 규칙, 그러나 플랫폼에 특정한 것이 있습니다 해결책 그것은 나를 위해 일합니다.

도움이 되었습니까?

해결책

Alexey Malistov가 제공 한 답변은 MSVC에서 약간의 수정으로 사용할 수 있습니다.

namespace 
{
    template<class T, int discriminator>
    struct is_complete {  
      static T & getT();   
      static char (& pass(T))[2]; 
      static char pass(...);   
      static const bool value = sizeof(pass(getT()))==2;
    };
}
#define IS_COMPLETE(X) is_complete<X,__COUNTER__>::value

불행히도, 카운터 사전 정의 된 매크로는 표준의 일부가 아니므로 모든 컴파일러에서 작동하지 않습니다.

다른 팁

template<class T>
struct is_complete {
    static T & getT();
    static char (& pass(T))[2];
    static char pass(...);

    static const bool value = sizeof(pass(getT()))==2;
};

조금 늦었을 수도 있지만 지금까지 C ++ 11 솔루션은 완전한 유형과 추상 유형 모두에서 작동하지 않았습니다.

그래서 여기 있습니다.

VS2015 (v140), g ++> = 4.8.1, clang> = 3.4에서는 다음과 같습니다.

template <class T, class = void>
struct IsComplete : std::false_type
{};

template <class T>
struct IsComplete< T, decltype(void(sizeof(T))) > : std::true_type
{};

Bat-ulzii luvsanbat 덕분에 : https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015 Update-1/

VS2013 (v120) :

namespace Details
{

    template <class T>
    struct IsComplete
    {
        typedef char no;
        struct yes { char dummy[2]; };

        template <class U, class = decltype(sizeof(std::declval< U >())) >
        static yes check(U*);

        template <class U>
        static no check(...);

        static const bool value = sizeof(check< T >(nullptr)) == sizeof(yes);
    };

} // namespace Details


template <class T>
struct IsComplete : std::integral_constant< bool, Details::IsComplete< T >::value >
{};

이것은 인터넷에서 영감을 받았습니다 정적은 템플릿 타이프 이름 t가 완료되지 않았다고 주장합니까?

나는 당신이 그런 구현을 할 수 없을까 봐 두렵습니다 is_complete 유형 특성. @alexey가 제공 한 구현은 G ++ 4.4.2 및 G ++ 4.5.0에서 컴파일하지 못합니다.

오류 : 'static char (& is_complete :: pass (t)) [2] [2]의 인수 초기화 1 [t = foo]'

내 Mac에서 G ++ 4.0.1 평가 is_complete<Foo>::value 어디 struct Foo; 불완전한 수익률입니다 true 컴파일러 오류보다 훨씬 나쁩니다.

T 번역 장치에 따라 동일한 프로그램에서 완전하고 불완전 할 수 있지만 항상 동일한 유형입니다. 결과적으로 위에서 언급 한 바와 같이 is_complete<T> 항상 같은 유형입니다.

당신이 존중한다면 ODR 가질 수 없습니다 is_complete<T> 사용되는 위치에 따라 다른 값으로 평가합니다. 그렇지 않으면 그것은 당신이 다른 정의를 가지고 있음을 의미합니다 is_complete<T> 어떤 ODR이 금지됩니다.

편집 : 허용 된 답변으로, 나는 자신이 __COUNTER__ 매크로는 다른 것을 인스턴스화합니다 is_complete<T, int> 매번 입력하십시오 IS_COMPLETE 매크로가 사용됩니다. 그러나 GCC를 사용하면 Sfinae가 처음부터 일할 수 없었습니다.

이를 해결하려면 템플릿의 정의를 변경하려고 시도하면 ODR 규칙을 위반하는 경우 (의 조합이지만) 특성 템플릿의 기본 인수에서 계산을 수행해야합니다. __COUNTER__ 그리고 namespace {} ODR에서 일할 수 있습니다).

이것은 C ++ 11으로 작성되었지만 적당히 최근 C ++ 11 호환 컴파일러의 C ++ 03 모드에서 작동하도록 조정할 수 있습니다.

template< typename t >
typename std::enable_if< sizeof (t), std::true_type >::type
is_complete_fn( t * );

std::false_type is_complete_fn( ... );

template< typename t, bool value = decltype( is_complete_fn( (t *) nullptr ) )::value >
struct is_complete : std::integral_constant< bool, value > {};

온라인 데모.

기본 인수는 템플릿의 이름이 지정된 위치에 평가되므로 다른 정의간에 문맥 상 전환 할 수 있습니다. 각 사용마다 다른 전문화와 정의가 필요하지 않습니다. 당신은 하나만 필요합니다 true 그리고 하나를 위해 false.

규칙은 §8.3.6/9에 제공되며 기본 인수 및 기본 템플릿 경사 기능에 동일하게 적용됩니다.

기본 인수는 함수가 호출 될 때마다 평가됩니다.

그러나 템플릿 내부에서 이것을 사용하면 ODR을 위반하는 것이 거의 확실합니다. 불완전한 유형에 인스턴스화 된 템플릿은 전체 유형에 인스턴스화 된 경우와 다르게 수행해서는 안됩니다. 나는 개인적으로 이것만을 원한다 static_assert.

또한,이 원칙은 다른 방향으로 가고 싶다면 도움이 될 수 있습니다. 구현하다 의 기능 __COUNTER__ 템플릿 및 과부하 사용.

관련이없는 질문에 대한 답변 (나에게 제공하지 않은)이 is_complete<T> 주형.

정답은 여기. 나는 실수로 신용을 얻지 않기 위해 아래에 붙여 넣지 않습니다.

불완전한 유형의 크기가 0이 될 것이라고 보장하는 표준에서 찾을 수 없습니다. 그러나 어느 시점에서 T가 불완전하지만 해당 번역 장치의 뒷부분에서 완료되면 T 참조에 대한 모든 참조가 필요합니다. 동일한 유형으로 - 읽은대로 T가 불완전한 곳에 불완전하더라도 T가 해당 번역 장치 어딘가에 완료되면 완료되었다고 말해야합니다.

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