Mam następujący kod (Przepraszam za dużego fragmentu kodu, ale nie mogłem sprowadzić więcej)niejednoznaczne szablon niesamowitość
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;
}
Ale to nie skompilować z gcc (v4.3) z
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
OK, więc jest niejednoznaczna. ale nie spodziewałem się, że to będzie problem, ponieważ przy użyciu specjalizacji prawie zawsze będzie jakaś niejednoznaczność. Jednak ten błąd jest wywoływany tylko podczas używania klasy z enable_if<...>
, jeśli zastąpię ją klasą podobną do poniższej, nie ma problemu.
template <typename X, typename Y>
struct Foo<X, Y, void > { enum { value = 2 }; };
Dlaczego ta klasa nie wywołuje dwuznaczności, podczas gdy inni nie? Czy te dwie rzeczy nie są takie same dla klas o wartości true :: value? W każdym razie wszelkie wskazówki dotyczące tego, co robię źle, są doceniane.
Dzięki za odpowiedzi, moim prawdziwym problemem (aby kompilator wybrać swój pierwszy specjalizacji) został rozwiązany przez zastąpienie struct Foo<X, Base<X>, void>
z struct Foo<X, Base<X>, typename enable_if< Base<X> >::type >
który wydaje się działać tak, jak chcę.
Edytor przecinków nie jest wysiwyg w stosunku do
Naprawiłem go wcześniej, nadpisałeś moje zmiany :) Jeśli chcesz, możesz wrócić do mojej edycji (użyłem przycisku "10101", który automatycznie oznacza rzeczy jako kod, powinieneś użyć ten przycisk też). –
Uhjm ... Zrobiłem to ponownie bez czytania twojego komentarza litb –