Является ли локальный класс зависимым, если он объявлен в шаблоне функции?

Текущие компиляторы C ++ (последние gcc, clang) требуют typename Ключевое слово в примере ниже:

template<class T>
struct A
{
};

template<class T>
void f(T)
{
struct C
{
};
typedef typename A<C>::Type Type; // typename required
}

Если typename опущен gcc (4.9, 5.0) сообщает об ошибке:

need 'typename' before 'A<f(T)::C>::Type' because 'A<f(T)::C>' is a dependent scope

Этот пример хорошо сформирован в соответствии с моим прочтением стандарта C ++ 11.

Такое поведение, по-видимому, охватывается следующей формулировкой:

[Temp.dep.type] / 8

Тип зависит, если он

  • параметр шаблона,

  • член неизвестной специализации,

  • вложенный класс или перечисление, являющееся членом текущего экземпляра,

  • cv-квалифицированный тип, где cv-неквалифицированный тип является зависимым,

  • составной тип, построенный из любого зависимого типа,

  • тип массива, созданный из любого зависимого типа или размер которого определяется константным выражением
    это зависит от стоимости,

  • простой-шаблон-идентификатор, в котором либо имя шаблона является параметром шаблона, либо любым из шаблона
    arguments является зависимым типом или выражением, которое зависит от типа или значения, или

  • обозначается decltype (выражение), где выражение зависит от типа.

Тем не менее, в соответствии с [class.local] класс C это местный класс, а не вложенными учебный класс. Если так, то почему A<C> лечиться как зависимый?

РЕДАКТИРОВАТЬ

Для бонусных баллов, если пример изменен путем добавления перечисления члена в C следующее:

template<typename T>
struct A
{
typedef T Type;
};

template<class T>
void f(T)
{
struct C
{
enum { value = T::value };
};
typedef typename A<C>::Type Type; // typename required
}

Должен A<C> теперь относиться как к зависимым?

5

Решение

Согласно моему пониманию (и нынешней редакции стандарта), C в вашем примере это не зависит. Ни то, ни другое A<C>::Type, Итак typename не требуется.

Существует фундаментальное различие между вложенными классами шаблонов классов и локальными классами в шаблонах функций: последние не могут быть специализированными, поэтому любая ссылка на локальный класс внутри шаблона функции является однородной. То есть в каждой специализации f, C относится к классу C что определено в этом шаблоне функции f, Это не относится к шаблонам классов, поскольку вы действительно можете явно специализировать членов самостоятельно (как описано в [temp.expl.spec] /(1.6)):

template <typename T>
class A { class C{}; };

template <>
class A<int>::C { int i; };

Тем не мение:

Тип зависит, если он

  • составной тип, построенный из любого зависимого типа,

Так что, если определение было сделано как в пример дипа, C будет зависеть от того, как он построен из T,
Существуют неясности в формулировке стандартов, которые обсуждаются в разделе комментариев, например об определениях функций-членов, которые зависят от T и как это переносится на зависимость классов.

4

Другие решения

Следующее — мои рассуждения, надеюсь, это поможет. Местный C не создается до f экземпляр. Так, A<C> не является экземпляром и непрозрачен для компилятора, когда он его видит. Из-за непрозрачности компилятор не может определить, A<C>::Type является именем вложенного типа или членом данных или методом. Однако по умолчанию компилятор не видит A<C>::Type как имя вложенного типа. Следовательно, необходима явная спецификация.

0

Похоже, в стандарте нет ничего, чтобы утверждать, что typename ключевое слово должно быть необходимо здесь. Формулировка также явно не указывает на иное, что, возможно, привело к тому, что GCC предпринял небольшой шаг в лечении f<T>(T)::C (будучи локальным классом в специализации шаблона функции) в зависимости от T — по расширению, это сделало бы A<[f<T>(T)::]C>::Type зависимый.

Основной дефект 1484 не был поднят конкретно по этому вопросу, но я думаю, что дополнительный ненормативный текст, который он предлагает, проясняет намерение, и, будь это в стандарте, GCC не будет требовать typename Ключевое слово здесь.

0
По вопросам рекламы [email protected]