문제

다음 코드가 있습니다 (대형 코드 청크에 대해 죄송하지만 더 이상 좁을 수 없었습니다).

template <bool B>
struct enable_if_c {
      typedef void type;
};

template <>
struct enable_if_c<false> {};

template <class Cond>
struct enable_if : public enable_if_c<Cond::value> {};

template <typename X>
struct Base { enum { value = 1 }; };

template <typename X, typename Y=Base<X>, typename Z=void>
struct Foo;

template <typename X>
struct Foo<X, Base<X>, void> { enum { value = 0 }; };

template <typename X, typename Y>
struct Foo<X, Y, typename enable_if<Y>::type > { enum { value = 1 }; };

int main(int, char**) {
        Foo<int> foo;
}

그러나 GCC (v4.3)로 컴파일하지 못합니다.

foo.cc: In function ‘int main(int, char**)’:
foo.cc:33: error: ambiguous class template instantiation for ‘struct Foo<int, Base<int>, void>’
foo.cc:24: error: candidates are: struct Foo<X, Base<X>, void>
foo.cc:27: error:                 struct Foo<X, Y, typename enable_if<Y>::type>
foo.cc:33: error: aggregate ‘Foo<int, Base<int>, void> foo’ has incomplete type and cannot be defined

좋아, 그래서 모호하다. 그러나 나는 전문화를 사용할 때 거의 항상 모호함이 될 것으로 기대하지 않았다. 그러나이 오류는 클래스를 사용할 때만 트리거됩니다. enable_if<...>, 다음과 같은 클래스로 교체하면 아무런 문제가 없습니다.

template <typename X, typename Y>
struct Foo<X, Y, void > { enum { value = 2 }; };

이 클래스는 왜 다른 사람들이 모호함을 유발하지 않습니까? True :: Value를 가진 클래스에서도 두 사람이 동일하지 않습니까? 어쨌든, 내가 잘못하고있는 일에 대한 힌트는 감사합니다.

답변 주셔서 감사합니다, 나의 진짜 문제 (컴파일러가 내 첫 번째 전문화를 선택하도록하기 위해)를 교체하여 해결했습니다. struct Foo<X, Base<X>, void> ~와 함께 struct Foo<X, Base<X>, typename enable_if< Base<X> >::type > 내가 원하는 방식으로 작동하는 것 같습니다.

도움이 되었습니까?

해결책

질문의 요점은 다음과 같습니다.

template <typename X, typename Y, typename Z>
struct Foo {};

template <typename X>
struct Foo<X, Base<X>, void> {};                   // #1

template <typename X, typename Y>
struct Foo<X, Y, typename whatever<Y>::type> {};   // #2

그리고 당신은 그것을 일치 시키려고합니다

Foo<int, Base<int>, void>

분명히, 두 전문화 모두 (첫 번째)와 일치합니다 X = int, 두 번째 X = int, Y = Base<int>).

표준에 따르면 섹션 14.5.4에 따르면, 더 일치하는 전문화가있는 경우, 그 중 부분 순서 (14.5.5.2에 정의 된대로)가 구성되고 가장 전문화 된 가장 전문화 된 것들이 사용됩니다. 그러나 귀하의 경우에는 어느 것도 다른 것보다 더 전문적이지 않습니다. (간단히 말해서, 템플릿은 다른 템플릿의 각 유형 매개 변수를 일부 유형으로 바꿀 수 있고 결과적으로 전자의 서명을 얻을 수 있다면 템플릿이 다른 것보다 더 특화되어 있습니다. whatever<Y>::type 그리고 당신은 대체합니다 Y ~와 함께 Base<X> 당신은 얻습니다 whatever<Base<X> >::type ~ 아니다 void, 즉 처리가 수행되지 않습니다.)

교체하는 경우 #2 ~와 함께

template <typename X, typename Y>
struct Foo<X, Y, void > {};                        // #3

그런 다음 후보 세트에는 다시 두 템플릿이 모두 포함되어 있지만 #1은 #3보다 더 특화되어 있으며 선택됩니다.

다른 팁

당신은 놓치지 않습니까?

<

상징?

나는 당신이 '<'를 놓치고 있다고 생각합니다. 템플릿은 다음과 같아야합니다.

template< typename T >
struct myStruct
{};

//OR

template< class T >
struct myStruct
{};
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top