Template-Spezialisierung nicht möglich
-
Huhu,
Wieso ist das folgende eigentlich nicht erlaubt?
template <typename T> struct valdef { typedef T value; }; template <typename> struct pop_back; template <digit... Head, digit Tail> struct pop_back<bigint<Head..., Tail>> : valdef<bigint<Head...>> {};=>
../main.cpp:6:10: error: 'value' in 'struct tmp::pop_back<tmp::bigint<5u, 6u, 7u> >' does not name a type
-
Gibt es ein komplettes Minimalbeispiel? Duerfen denn nach ... noch weitere Argumente folgen?
-
Was ist denn unklar? Angenommen ich habe einen bigint<1, 2, 3>, dann soll das Ergebnis ein bigint<1, 2> sein.
-
314159265358979 schrieb:
Was ist denn unklar? Angenommen ich habe einen bigint<1, 2, 3>, dann soll das Ergebnis ein bigint<1, 2> sein.
Wenn der Fehler ist, dass eine Typenbezeichnung ungültig ist, wäre es sehr nützlich, alle Typen genau zu kennen. Außerdem möchte man so etwas gerne mal selber ausprobieren und eine Korrektur ausprobieren, bevor man eine vermeintlich falsche Antwort gibt. Allein durch Draufstarren beantwortet niemand solche Fragen. Man fragt sich dann bloß ständig, was nun digit und bigint genau sind und ob der Fehler vielleicht dort liegt.
-
typedef unsigned char digit; template <digit...> struct bigint {};
-
Kompiliert bei mir mit gcc 4.7.0. Gib mal nen kompletten Testcase her, der das Problem erzeugt.
-
seldon schrieb:
Kompiliert bei mir mit gcc 4.7.0. Gib mal nen kompletten Testcase her, der das Problem erzeugt.
Sogar 4.4 schluckt das.
-
Naja, ohne benutzenden Code schluckt der bei Templates im Zweifel einiges. Mit dem, was bisher vorliegt, ist die Frage stumpf nicht zu beantworten.
-
Bestimmt verwendet pi insgeheim doch msvc++

EDIT um noch was produktives beizusteuern:
Ich vermute, dein Problem ist das hier:
typedef unsigned char digit; template< digit... > class bigint; template <typename T> struct valdef { typedef T value; }; template <typename> struct pop_back; template<> struct pop_back< bigint<> > { }; template <digit... Head, digit Tail> struct pop_back<bigint<Head..., Tail>> : valdef<bigint<Head...>> {}; int main() { pop_back< bigint< 1 > > f; }aggregate 'pop_back<bigint<1u> > f' has incomplete type and cannot be definedIch glaube das liegt daran, dass die Argumente von bigint so weit wie möglich in den Parameterpack Head... kommen, d.h. danach ist kein template parameter mehr für den Tail übrig, also ist die partielle Spezialisierung von pop_back nicht gültig für diese template - Instanzierung. (k.A. ob das so im Standard steht und wo)
-
Wird wohl daran liegen, was GorbGorb gesagt hat. Ich hab pop_back jetzt einfach umgeschrieben.
template <typename> struct pop_back; template <digit D> struct pop_back<bigint<D>> : valdef<bigint<>> {}; template <digit Head1, digit Head2, digit... Tail> struct pop_back<bigint<Head1, Head2, Tail...>> : valdef < typename push_front < Head1, typename pop_back<bigint<Head2, Tail...>>::value >::value > {};Ist zwar komplizierter, aber funktioniert. Und nein, ich verwende nicht MSVC.
-
@PI: Hast du vielleicht ein typename vergessen?
-
Ich vergesse keine typenames. Ich habe noch nie eines vergessen. Noch. Nie. Niemals.
-
314159265358979 schrieb:
Ich vergesse keine typenames. Ich habe noch nie eines vergessen. Noch. Nie. Niemals.
Da greift jetzt so etwas ähnliches wie Poes Gesetz, oder?
-
Hihi. Musste das eben nachschlagen

Ja, ich meine das ernst. Schick mir 10.000 LOC Heavy-Template-Shit in dem typenames fehlen und ich finde alle Stellen, ohne Zuhilfenahme eines Tools.
Ich bin da besser als somancher *hust MSVC hust* Compiler.
-
GorbGorb schrieb:
Ich glaube das liegt daran, dass die Argumente von bigint so weit wie möglich in den Parameterpack Head... kommen, d.h. danach ist kein template parameter mehr für den Tail übrig, also ist die partielle Spezialisierung von pop_back nicht gültig für diese template - Instanzierung. (k.A. ob das so im Standard steht und wo)
Sehr gut.
Mit ein bisschen Überlegung erkennt man, dass das Problem bie Klassentemplates nur bei partieller Spezialisierung auftritt. Bei expliziter Spezialisierung sind sowieso keine Parameter zu deduzieren, und bei Primärtemplates steht ein eventuell vorhandenes Parameterpack immer am Ende.Fange mit der Suche also in 14.5.5.1 [temp.class.spec.match] an
...
2 A partial specialization matches a given actual template argument list if the template arguments of the
partial specialization can be deduced from the actual template argument list (14.8.2).
...Weiter nach 14.8.2.5 [temp.deduct.type] (hier geht es um die Deduktion eines Typen, nämlich bigint <...>)
...
9 If P has a form that contains <T> or <i>, then each argument Pi of the respective template argument list
P is compared with the corresponding argument Ai of the corresponding template argument list of A. If
the template argument list of P contains a pack expansion that is not the last template argument, the
entire template argument list is a non-deduced context. If Pi is a pack expansion, then the pattern of Pi
is compared with each remaining argument in the template argument list of A. Each comparison deduces
template arguments for subsequent positions in the template parameter packs expanded by Pi. During
partial ordering (14.8.2.4), if Ai was originally a pack expansion:
— if P does not contain a template argument corresponding to Ai then Ai is ignored;
— otherwise, if Pi is not a pack expansion, template argument deduction fails.