Я портирую свой код окон C++ (msvc и Intel) к Linux (g ++). Код использует много шаблонов (мне нравится метапрограммирование ;-). Но я не могу скомпилировать этот код:
template <class TA>
struct A
{
template <class TAB> struct B;
};
template <class TC>
struct C {};
template <class TD>
struct D
{
template <class TTD> class T {};
};
template<class TA>
template<class TBA>
struct A<TA>::B : C<typename D<TA>::T<TBA> >
{
int foo;
};
g ++ говорит мне что в определении A:: B, C класс имеет недопустимые аргументы шаблона. Но на msvc и Intel это работает хорошо! Какова проблема здесь? PS: Извините, я не могу отправить исходный код, потому что он является слишком сложным шаблоном. Но этот пример является фактически тем же и дает ту же ошибку на g ++.Спасибо.
ОБНОВЛЕНИЕ: я нашел, что проблема находится в аргументе TBA T. g ++ doensn't как использование второго шаблона в определении.
Вам нужен шаблон
ключевое слово
template<class TA>
template<class TBA>
struct A<TA>::B : C<typename D<TA>::template T<TBA> >
{
int foo;
};
GCC правильный, чтобы дать здесь диагностику. Это связано с тем, что T
не может быть найден в зависимой области D
. Значение <
после него зависит от того, является ли T
шаблоном или нет. Стандарт говорит, что T
не должен рассматриваться как шаблон, и поэтому за T
не может следовать список аргументов шаблона.
шаблон
похож на typename
в том смысле, что он сообщает компилятору обрабатывать T
как шаблон, а <
является началом аргумента. список на всякий случай. В Стандарте говорится в параграфах 14.2 / 2
и 14.2 / 4
Для того, чтобы имя шаблона явно определялось аргументами шаблона, имя должно быть известно, чтобы ссылаться на к шаблону.
Когда имя специализации шаблона элемента появляется после. или -> в выражении-постфиксе, или после спецификатора вложенного-имени в квалифицированном-идентификаторе, а постфиксное-выражение или квалифицированный-идентификатор явно зависит от параметра-шаблона (14.6.2), имя шаблона элемента должно быть с префиксом шаблона ключевого слова. В противном случае предполагается, что имя не является шаблоном.
В вашем случае T
появляется после спецификатора вложенного имени D
, который зависит от параметра шаблона TA
. Для правильного анализа спецификатора имени-типа конструкция D
должна интерпретировать T
как имя шаблона класса, который 14.2
запрещает.
По этой теме всегда неплохо попробовать и скомпилировать с помощью Clang
main1.cpp:21:37: error: use 'template' keyword to treat 'T' as a dependent template name
struct A<TA>::B : C<typename D<TA>::T<TBA> >
^
template
1 error generated.