Pierwsza część kodu, następnie jakiś kontekst, to pytanie:o zmiennej liczbie argumentów aliasy szablonu jako argumentów szablonu
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;
Zarówno dzyń 3.3 i gcc 4.8.1 skompilować to bez błędu, stosując metafunkcji tożsamość int
, więc zarówno wyrażenia oceniają domyślnie int
(zero).
Fakt id
jest template <typename>
podczas apply1
, apply2
spodziewać template <typename...>
nie dotyczą mnie na pierwszym miejscu. Jednak jest całkiem wygodne, że ten przykład działa, ponieważ inaczej metakunkcje, takie jak apply1
, apply2
musiałyby być o wiele bardziej zaangażowane. Z drugiej strony takie aliasy szablonów powodują poważne problemy w kodzie w świecie rzeczywistym, których nie mogę tu odtworzyć: częste błędy wewnętrznego kompilatora dla gcc i rzadsze nieoczekiwane zachowanie dla klang (tylko w bardziej zaawansowanych testach SFINAE).
Po miesiącach prób i błędów, ja teraz zainstalować i wypróbować kodu na (doświadczalnie) gcc 4.9.0, i tu pojawia się błąd:
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, więc wydaje się, ten kod nie był jest ważny przez cały ten czas, ale gcc rozbił się na różne sposoby, zamiast zgłaszać błąd. Co ciekawe, podczas gdy apply1
, apply2
wydaje się być równoważny, błąd jest zgłaszany tylko dla apply2
(co jest znacznie bardziej przydatne w praktyce). Jeśli chodzi o klang, naprawdę nie mogę powiedzieć.
W praktyce wydaje mi się, że nie mam innego wyjścia, jak pogodzić się z gcc 4.9.0 i poprawić kod, nawet jeśli stanie się on znacznie bardziej złożony.
Teoretycznie chciałbym wiedzieć, co standard mówi: czy ten kod jest ważny? Jeśli nie, to czy nieprawidłowe jest również użycie apply1
? lub tylko apply2
?
EDIT
Właśnie w celu wyjaśnienia, że wszystkie problemy, jakie miał do tej pory znajdują się aliasy szablonie, a nie elemencie szablonu. Na przykład, należy rozważyć następujące zmiany:
template <typename T> struct id1 { using type = T; };
// ...
cout << typename apply1 <id1, int>::type() << endl;
cout << typename apply2 <id1>::map <int>::type() << endl;
To kompiluje i drukuje 0
w obu przypadkach na brzękiem 3.3, GCC 4.8.1, GCC 4.9.0.
W większości przypadków moje obejścia wprowadziły pośredni szablon struct przed aliasem. Jednak teraz próbuję użyć metapunkcji do parametryzowania ogólnych testów SFINAE iw tym przypadku muszę użyć aliasów bezpośrednio, ponieważ nie powinno się tworzyć instancji w structs. Aby uzyskać pewien pomysł, fragment rzeczywistego kodu to here.
Komunikat o błędzie eksperymentalnego GCC 4.9 nie ma dla mnie sensu, a FWIW Myślę, że kod jest prawidłowy. –
Powiązany? http://stackoverflow.com/q/18724698/420683 – dyp
Dzięki, to pytanie jest związane z tym, że szablony zajmujące się specjalnymi przypadkami, takimi jak 'foo',' foo2', 'foo_variadic' itd., są dokładnie tym, co planowałem poprawić kod, jeśli muszę. Jednak, jak już wcześniej edytowałem, moje problemy pojawiają się tylko z aliasami szablonów. – iavr