Здесь требуется имя типа или нет?

Рассмотрим код:

#include <memory>

template <class T, class Deleter = std::default_delete<T>>
class unique_ptr_wrapper: public std::unique_ptr<T, Deleter>
{
public:
    using typename std::unique_ptr<T, Deleter>::unique_ptr;
    operator T* () const {return this->get();}
};

int main()
{
    unique_ptr_wrapper<int> upw{new int{42}};
}

g++5.1 компилирует нормально, хотя clang++ жалуется

ошибка: имя типа разрешено только для идентификаторов

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

EDIT Код компилируется без typename как g++, так и clang++.


ОБНОВЛЕНИЕ Похоже, это ошибка g++, я сообщил об этом здесь.


person vsoftco    schedule 31.05.2015    source источник
comment
В интересах завершения матрицы, компилируется ли это на обе цепочки инструментов без typename ?   -  person WhozCraig    schedule 31.05.2015
comment
unique_ptr — это идентификатор. Но здесь он называет конструктор, а не тип, поэтому typename не подходит.   -  person aschepler    schedule 31.05.2015
comment
@WhozCraig да, он компилируется в обоих случаях без typename.   -  person vsoftco    schedule 31.05.2015
comment
@aschepler Я тоже в это верю, так что это похоже на ошибку g++ (если не требуется диагностика).   -  person vsoftco    schedule 31.05.2015


Ответы (1)


[class.inhctor]/p1, выделение мое:

объявление-использования (7.3.3), которое называет конструктор, неявно объявляет набор наследующих конструкторов.

Конструктор не является типом.

[temp.res]/p3-4:

3 Когда квалифицированный-id предназначен для ссылки на тип, который не является членом текущего экземпляра (14.6.2.1), а его описатель вложенного имени ссылается на зависимый тип, перед ним должно стоять ключевое слово typename, образующее спецификатор имени типа. Если квалифицированный идентификатор в спецификаторе имени типа не обозначает тип, программа имеет неправильный формат.

4 Если специализация шаблона создается для набора аргументов-шаблона, так что квалифицированный-id с префиксом typename не обозначает тип, специализация неверна. сформировался. Обычный поиск полного имени (3.4.3) используется для поиска полного идентификатора даже при наличии typename.

[класс.качество]/p2:

В поиске, в котором имена функций не игнорируются, а описатель вложенного имени назначает класс C:

  • если имя, указанное после описателя вложенного имени, при поиске в C является внедренным именем класса из C (пункт 9), или

  • в декларации-использования (7.3.3), которая является декларацией-членом, если имя, указанное после вложенного-спецификатора-имени, совпадает с идентификатором или simple-template-id template-name в последнем компоненте вложенного-имени -спецификатор,

вместо этого имя считается именем конструктора класса C.

Применяя правила «обычного поиска полного имени», найденные в [class.qual], std::unique_ptr<T, Deleter>::unique_ptr называет конструктор. Он не обозначает тип. Следовательно, судя по приведенной выше цитате из [temp.res], программа некорректна (требуется диагностика).

Другими словами, это похоже на ошибку GCC (хотя сообщение об ошибке Clang тоже нуждается в некотором улучшении).

person T.C.    schedule 31.05.2015
comment
Кроме того, в 7.3.3 [namespace.udecl]/19 говорится, что если using-declaration использует ключевое слово typename и указывает зависимое имя (14.6.2), имя, представленное using- объявление рассматривается как typedef-name (7.1.3). поэтому, если это что-то значит, то using typename ... должен объявить определение типа, а не наследующие конструкторы. - person Jonathan Wakely; 05.06.2015