рекурсивно вложенные шаблоны - ошибка gcc? - PullRequest
6 голосов
/ 02 мая 2011

У меня есть следующий фрагмент.

template< typename T >
struct f
{
  template< typename V >
  struct a : f
  {};
};

int main ()
{
  f<int>::a<int>::a<double> x;
}

Он компилируется без предупреждений в GCC 4.4.5, а также в MSVC 2010, но не в GCC 4.5.2 - при этом я получаю следующие ошибки:

test.cc: In function 'int main()':
test.cc:11:21: error: expected primary-expression before 'double'
test.cc:11:21: error: expected ';' before 'double'

Так что, хотя я не вижу в этом ничего нестандартного, вопрос обязателен - это законно в C ++? Кроме того, если это так, как я могу отправить отчет об ошибке в GCC? (

edit : Небольшой фон для любопытных:

Это должно быть частью шаблонного метапрограммирования. f в основном имеет структуру шаблонного класса метафункций с apply вместо a (конечно, вложенный type из apply опущен, поэтому мы можем сосредоточиться на самой структуре).

Наследование в этом случае является стандартным устройством для привязки возвращаемых значений метафункций. Этот фрагмент пытается достичь класса метафункций, который рекурсивно дает себя при оценке.

edit2 : позвольте мне поместить один и тот же фрагмент немного по-другому:

template< typename T >
struct f
{
  template< typename V > struct a;
};

template< typename T >
template< typename V >
struct f<T>::a : f<T>
{};

int main ()
{
  f<int>::a<int>::a<double> x;
}

Это выдает ту же ошибку. Я думаю, что это опровергает аргумент неполного типа.

Ответы [ 4 ]

4 голосов
/ 02 мая 2011

В существующих ответах было несколько хороших заметок. Во-первых, тип f является неполным во время определения вложенного шаблона класса, но f является зависимым типом. Теперь, если вы создадите экземпляр шаблона вложенности (f), он будет создавать объявление вложенного шаблона (члена). Обратите внимание, что объявление члена не включает список базовых предложений, поэтому ему не нужны полные базовые классы. После того, как шаблон вложенности был создан неявно, f завершен, и когда дело доходит до создания экземпляра определения члена, больше не должно быть проблем. Так что я не думаю, что комо здесь правильно жаловаться.

Другая ошибка заключается в том, что на самом деле f<int>::a<int>::a называет конструктор a<int> и требует, чтобы он был шаблоном конструктора (с <int> в качестве аргументов шаблона). Основа этого была DR # 147 .

Перевод в конструктор не выполняется, когда имя квалификатора не является классом введенного имени класса. Например, если это производный класс, ваш код становится действительным (как выяснили некоторые ответы).

2 голосов
/ 02 мая 2011

Хороший вопрос.Кажется, это проблема с gcc для template рекурсивного объявления.Потому что, если бы были сплошные классы, то это дает ошибку, и в идеале это должно быть объявлено как:

struct Out {
  struct In;
};
struct Out::In : Out {};
1 голос
/ 02 мая 2011

похоже, что GCC 4.5 считает, что вы указали конструктор.

один из возможных обходных путей:

template<typename T>
struct f {

    template<typename V>
    struct a : f {

        template<typename Z>
        struct q {
            typedef a<Z> Q;
        };
    };
};

int main() {
    f<int>::a<int>::q<double>::Q x;
    return 0;
}
0 голосов
/ 02 мая 2011

Используя Comeau онлайн, можно предположить, что f является неполным типом в том месте, где вы используете его в качестве базового класса, и поэтому не подходит.

"ComeauTest.c", line 5: error: incomplete type is not allowed
    struct a : f

У меня нет лязгаэкземпляр под рукой к сожалению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...