Zuerst einige Code, dann einiger Kontext, dann ist die Frage:Variadische Vorlage Aliasnamen als Template-Argument
template <typename T> using id = T;
template <template <typename...> class F, typename... T>
using apply1 = F <T...>;
template <template <typename...> class F>
struct apply2
{
template <typename... T>
using map = F <T...>;
};
// ...
cout << apply1 <id, int>() << endl;
cout << apply2 <id>::map <int>() << endl;
Beiden Klirren 3.3 und gcc 4.8.1 dies ohne Fehler kompilieren, um die Identität metafunction zu int
Anwendung, so dass beide Ausdrücke bewerten zu einem Standard int
(Null).
Die Tatsache, dass id
a template <typename>
während apply1
erwarten apply2
ein template <typename...>
tat mir Sorge in erster Linie. Es ist jedoch ziemlich praktisch, dass dieses Beispiel funktioniert, weil andernfalls Metafunktionen wie apply1
, apply2
so viel mehr beteiligt sein müssten.
Auf der anderen Seite verursachen solche Template-Aliase ernsthafte Probleme im realen Code, die ich hier nicht reproduzieren kann: häufige interne Compiler-Fehler für gcc und weniger häufiges unerwartetes Verhalten für clang (nur in fortgeschritteneren SFINAE-Tests).
Nach Monaten der Versuch und Irrtum, ich jetzt installieren und versuchen, den Code auf der (experimentell) gcc 4.9.0, und hier kommt der Fehler:
test.cpp: In instantiation of ‘struct apply2<id>’:
test.cpp:17:22: error: pack expansion argument for non-pack parameter ‘T’ of alias template ‘template<class T> using id = T’
using map = F <T...>;
^
Ok, so scheint es, dieser Code nicht war die ganze Zeit gültig, aber gcc stürzte auf verschiedene Arten ab, anstatt den Fehler zu melden. Interessanterweise, während apply1
, apply2
als äquivalent erscheinen, wird der Fehler nur für apply2
gemeldet (was in der Praxis viel nützlicher ist). Was den Klang betrifft, kann ich wirklich nicht sagen.
In der Praxis scheint es, als ob ich nicht anders als mit gcc 4.9.0 zu gehen und den Code zu korrigieren, obwohl es viel komplexer werden wird.
In der Theorie würde ich gerne wissen, was der Standard sagt: Ist dieser Code gültig? Wenn nicht, ist die Verwendung von apply1
auch ungültig? oder nur apply2
?
EDIT
Nur um zu klären, dass alle Probleme, die ich bisher auf Vorlage Aliase verweisen gehabt haben, nicht Vorlage structs. Betrachten wir zum Beispiel die folgende Änderung:
template <typename T> struct id1 { using type = T; };
// ...
cout << typename apply1 <id1, int>::type() << endl;
cout << typename apply2 <id1>::map <int>::type() << endl;
Dies kompiliert fein und Drucke 0
in beiden Fällen auf Klirren 3.3, gcc 4.8.1, gcc 4.9.0.
In den meisten Fällen haben meine Problemumgehungen eine Zwischenschablonenstruktur vor dem Alias eingeführt. Ich versuche jedoch, Metafunktionen zu verwenden, um generische SFINAE-Tests zu parametrisieren, und in diesem Fall muss ich Aliase direkt verwenden, da Strukturen nicht instanziiert werden sollten. Nur um eine Idee zu bekommen, ist ein Stück des tatsächlichen Codes here.
Die Fehlermeldung des experimentellen GCC 4.9 macht für mich keinen Sinn, und FWIW Ich denke, der Code ist gültig. –
In Verbindung stehend? http://StackOverflow.com/q/18724698/420683 – dyp
Danke, diese Frage ist in Bezug darauf, dass Vorlagen mit Sonderfällen wie 'foo',' foo2', 'foo_variadic' etc. genau die Art und Weise sind, die ich plante zu korrigieren der Code, wenn ich muss. Wie ich oben bearbeitet habe, erscheinen meine Probleme jedoch nur bei Vorlagenaliasnamen. – iavr