проблема шаблона g ++ - PullRequest
       4

проблема шаблона g ++

6 голосов
/ 25 июня 2010

Я портирую свой код Windows 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 ++ не нравится использование второго шаблона в определении.

1 Ответ

10 голосов
/ 25 июня 2010

Вам нужно ключевое слово template

template<class TA>
    template<class TBA>
struct A<TA>::B : C<typename D<TA>::template T<TBA> >
{
    int foo;
};

GCC правильно поставить здесь диагностику. Это потому, что T нельзя найти в зависимой области действия D<TA>. Значение < после него зависит от того, является ли T шаблоном или нет. Стандарт гласит, что T следует считать не шаблоном, и поэтому T не может сопровождаться списком аргументов шаблона.

template похож на typename в том смысле, что он указывает компилятору обрабатывать T как шаблон, а < является началом списка аргументов в любом случае. Стандарт гласит в пунктах 14.2/2 и 14.2/4

Чтобы имя шаблона было явно определено аргументами шаблона, должно быть известно, что имя относится к в шаблон.

Когда имя специалиста шаблона участника появляется после. или -> в выражении postfix или после спецификатора nested-name в квалифицированном идентификаторе, а выражение postfix или квалифицированный идентификатор явно зависит от параметра-шаблона (14.6.2), имя шаблона элемента должно быть с префиксом шаблона ключевого слова. В противном случае предполагается, что имя не является шаблоном.

В вашем случае T появляется после спецификатора вложенного имени D<TA>, который зависит от параметра-шаблона TA. Для правильного разбора спецификатора typen конструкция D<TA>::T<TBA> должна интерпретировать 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.
...