Разница в поведении clang и gcc при попытке запутать их, используя псевдоним шаблона с фиктивным параметром, чтобы скрыть базовый класс

Рассмотрим следующую программу на C ++:

class A
{
    protected:
        int x;
};

template<typename X>
using B = A;

template<typename T>
class C : public B<T>
{
    public:
        void f()
        {
            x = 0;
        }
};

int main()
{
}

При компиляции с помощью clang и gcc с использованием -std=c++17 -pedantic-errors в качестве параметров компиляции они ведут себя по-разному: Clang компилируется без каких-либо ошибок, но gcc выдает ошибку компиляции о невозможности поиска идентификатора x.

Что в этом случае говорит стандарт c ++? Разрешены ли оба поведения, или в этом случае в одном из компиляторов есть ошибка?

Ссылка на обозреватель компилятора: https://godbolt.org/z/EYvYrr


person Supremum    schedule 06.09.2020    source источник
comment
Я думаю, это может быть дубликат проблемы GCC: использование члена базового класса, который зависит от аргумента шаблона: In the definition of a class template or a member of a class template, if a base class of the class template depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.   -  person t.niese    schedule 06.09.2020
comment
@ t.niese Я не думаю, что это обман. В этом случае базовый класс не зависит от параметра шаблона. Вопрос в том, должен ли компилятор видеть, что он не зависим.   -  person HolyBlackCat    schedule 06.09.2020
comment
@HolyBlackCat - timsong-cpp.github.io/cppwp/n4659/temp .alias # 3 - определенно кажется, что быть зависимым - это вещь   -  person StoryTeller - Unslander Monica    schedule 06.09.2020
comment
да. Вопрос в том, считается ли базовый класс зависимым или нет.   -  person Supremum    schedule 06.09.2020


Ответы (2)


Это похоже на CWG1390 и похоже, что поведение Clang соответствует соглашению CWG о том, как следует обрабатывать такие шаблоны псевдонимов. (заменяется с нетерпением во время определения шаблона):

1390. Зависимость от специализации шаблона псевдонима

Согласно 17.7.2.1 [temp.dep.type] параграф 8, тип является зависимым (среди прочего), если он

  • simple-template-id, в котором либо имя шаблона является параметром шаблона, либо любой из аргументов шаблона является зависимым типом или выражением, которое зависит от типа или значения

Это применимо к специализациям шаблона псевдонима, даже если результирующий тип не зависит от аргумента шаблона:

   struct B { typedef int type; };
   template<typename> using foo = B;
   template<typename T> void f() {
     foo<T>::type * x;  //error: typename required
   }

Оправдано ли изменение правил для подобных случаев?

Примечания с встречи в октябре 2012 г.

CWG согласилась, что в этом случае не требуется typename. В некотором смысле специализация шаблона псевдонима похожа на текущее создание экземпляра и может быть известна во время определения шаблона.

person Language Lawyer    schedule 06.09.2020

Для C ++ 17 здесь правильный GCC.

9 Тип является зависимым, если он

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

  • [...]

  • simple-template-id, в котором либо имя шаблона является параметром шаблона, либо любой из аргументов шаблона является зависимым типом или выражением, которое зависит от типа или значения, или является расширением пакета [Примечание: сюда входит внедренное имя-класса для шаблона класса, используемого без списка-аргументов-шаблонов. - конец примечания], или

B<T> - это простой-шаблон-идентификатор, его аргумент является зависимым типом, поэтому тип, обозначенный B<T>, является зависимым. При использовании зависимого типа в качестве базового класса любой унаследованный член должен быть либо полностью определен именем базового класса, либо доступен через this->.

person StoryTeller - Unslander Monica    schedule 06.09.2020
comment
Спасибо. Сообщено об ошибке: bugs.llvm.org/show_bug.cgi?id=47435 - person Supremum; 06.09.2020