Первый некоторый код, то определенный контекст, то возникает вопрос:VARIADIC псевдонимами шаблона в качестве аргументов шаблона
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;
Оба лязг 3,3 и GCC 4.8.1 транслируют это без ошибок, применяя metafunction идентичности к int
, так как выражения оцениваются по умолчанию int
(ноль).
Тот факт, что id
является template <typename>
в то время как apply1
, apply2
ожидать template <typename...>
касалась меня в первую очередь. Однако, это довольно удобно, что этот пример работает, потому что в противном случае метафоры, такие как apply1
, apply2
, должны были бы быть гораздо более активными.
С другой стороны, такие псевдонимы шаблонов вызывают серьезные проблемы в коде реального мира, которые я не могу воспроизвести здесь: частые ошибки внутреннего компилятора для gcc и менее частые неожиданные действия для clang (только в более сложных тестах SFINAE).
После нескольких месяцев проб и ошибок, я теперь установить и попробовать код на (экспериментальный) НКУ 4.9.0, и здесь возникает ошибка:
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, так что кажется, что этот код не был действителен все это время, но gcc разбился по-разному, а не сообщал об ошибке. Интересно, что в то время как apply1
, apply2
оказываются эквивалентными, ошибка сообщается только для apply2
(что гораздо более полезно на практике). Что касается clang, я действительно не могу сказать.
На практике кажется, что у меня нет другого выхода, кроме как пойти с gcc 4.9.0 и исправить код, хотя он станет намного сложнее.
В теории, я хотел бы знать, что говорит стандарт: действительно ли этот код действителен? Если нет, используется ли значение apply1
? или только apply2
?
EDIT
Просто чтобы прояснить, что все проблемы, которые я имел до сих пор относятся к шаблонным псевдонимам, а не шаблонные структур. Например, рассмотрим следующую модификацию:
template <typename T> struct id1 { using type = T; };
// ...
cout << typename apply1 <id1, int>::type() << endl;
cout << typename apply2 <id1>::map <int>::type() << endl;
Это нормально компилируется и печатает 0
в обоих случаях на лязгом 3.3, GCC 4.8.1, GCC 4.9.0.
В большинстве случаев мои обходные пути вводили промежуточную структуру шаблонов перед псевдонимом. Тем не менее, я сейчас пытаюсь использовать метафайлы для параметризации общих тестов SFINAE, и в этом случае я должен использовать псевдонимы напрямую, потому что структуры не должны создаваться. Чтобы получить представление, часть фактического кода here.
Сообщение об ошибке экспериментального GCC 4.9 не имеет для меня смысла, и FWIW Я считаю, что код действителен. –
Связанные? http://stackoverflow.com/q/18724698/420683 – dyp
Спасибо, этот вопрос связан с тем, что шаблоны, касающиеся особых случаев, таких как 'foo',' foo2', 'foo_variadic' и т. д., точно так же, как я планировал исправить код, если нужно. Однако, как я уже писал выше, мои проблемы появляются только с псевдонимами шаблонов. – iavr