Templatespezialisierung: Unterscheidung pointer und non-pointer type
-
Hi,
ich versuche gerade eine KlasseFoozusammen zu basteln, die folgendes möglich macht:Foo<int, -1> a; Foo<void*, nullptr> b;Die Klasse braucht einen Typ und einen ungültigen Wert für diesen Typ.
Mein Versuch:
template<typename Type, Type invalid> struct Foo { Type value = invalid; }; template<typename Type, Type* invalid> struct Foo<Type*, invalid> { Type value = invalid; int i; }; int main() { Foo<int, -1> a; a.value = 5; Foo<void*, nullptr> b; b.i = 5; }
main.cpp:19:4: error: no member named 'i' in 'Foo<void *, nullptr>'Anscheinend wird die Spezialisierunug nicht gematcht. Wie würde es richtig aussehen?
-
template<typename Type, Type *invalid> struct Foo<Type*, invalid> { Type *value = invalid; int i; };
-
Zeile 10:
Type* value = invalid;Anschließend compiliert und läuft es (Visual Studio 12)
-
Selber Fehler. Aber du hast recht, in der Spezialisierung müsste es
Type*sein.Nachtrag: clang++ 3.8.1 gibt mir den Fehler, g++ 6.2.1 akzeptiert den Code. clang Bug?
-
Biolunar schrieb:
Selber Fehler. Aber du hast recht, in der Spezialisierung müsste es
Type*sein.Nachtrag: clang++ 3.8.1 gibt mir den Fehler, g++ 6.2.1 akzeptiert den Code. clang Bug?
Nach meinem Verständnis wüsste ich nicht weshalb er auch im
void*-Fall nicht das erste Template instanzieren dürfte:template<Type = void*, void* invalid = nullptr> struct Foo { void* value = nullptr; };Sowas ähnliches hatte ich auch schon öfter und habe da bisher immer mit
std::enable_if<std::is_pointer<Type>>gearbeitet.Gruss,
FinneganP.S.: Wenn man wissen möchte wie man Pointer grundsätzlich unterscheidet, lohnt es sich vielleicht mal eine Implementierung von
std::is_pointeranzusehen. So auf Anhieb wüsse ich nicht wie ich da rangehen würde.
-
Finnegan schrieb:
Nach meinem Verständnis wüsste ich nicht weshalb er auch im
void*-Fall nicht das erste Template instanzieren dürfte […]Siehe 1) auf http://en.cppreference.com/w/cpp/language/partial_specialization#Partial_ordering
Habe mein Problem nun anders gelöst (ohne Spezialisierung). Trotzdem merkwürdig, dass clang den Code nicht mag.
-
Das Problem hat etwas mit Templateargumentdeduktion zu tun. Wenn wir das Ganze etwas umschreiben:
template <typename T, T x> struct S {}; template <typename T, T x> char foo(S<T, x>); static_assert( sizeof(foo(S<void*,nullptr>{}))==1, "");hat clang weiterhin die gleichen Schwierigkeiten.