2

Consider the following c++ program:

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()
{
}

When compiled with clang and gcc using -std=c++17 -pedantic-errors as compilation options they behave differently: Clang compiles without any errors, but gcc gives a compilation error about not being able to lookup the identifier x.

What does the c++ standard say in this case? Are both behaviours allowed, or does one of the compilers have a bug in this case?

Compiler explorer link: https://godbolt.org/z/EYvYrr

cigien
  • 57,834
  • 11
  • 73
  • 112
Supremum
  • 542
  • 7
  • 23
  • I think it's might be a duplicate to [GCC issue: using a member of a base class that depends on a template argument](https://stackoverflow.com/questions/11405): `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.` – t.niese Sep 06 '20 at 08:05
  • 1
    @t.niese I don't think it's a dupe. In this case the base class doesn't really depend on the template parameter. The question is whether the compiler is required to see that it's not dependent. – HolyBlackCat Sep 06 '20 at 08:08
  • 1
    @HolyBlackCat - https://timsong-cpp.github.io/cppwp/n4659/temp.alias#3 - Definitely seems like being dependent is a thing – StoryTeller - Unslander Monica Sep 06 '20 at 08:10
  • Yes. The question is if the base class is counted as dependent or not. – Supremum Sep 06 '20 at 08:13

2 Answers2

2

This looks similar to CWG1390, and looks like Clang's behavior is consistent with CWG agreement on how such alias templates should be handled (substituted eagerly, at template definition time):

1390. Dependency of alias template specializations

According to 17.7.2.1 [temp.dep.type] paragraph 8, a type is dependent (among other things) if it is

  • a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent

This applies to alias template specializations, even if the resulting type does not depend on the template argument:

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

Is a change to the rules for cases like this warranted?

Notes from the October, 2012 meeting:

CWG agreed that no typename should be required in this case. In some ways, an alias template specialization is like the current instantiation and can be known at template definition time.

Language Lawyer
  • 3,378
  • 1
  • 12
  • 29
1

For C++17, GCC is correct here.

9 A type is dependent if it is

  • a template parameter,

  • [...]

  • a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack expansion [ Note: This includes an injected-class-name of a class template used without a template-argument-list.  — end note ] , or

B<T> is a simple-template-id, its argument is a dependent type, therefore the type denoted by B<T> is dependent. When using a dependent type as a base class, any inherited member must be either fully qualified by it's base class name, or accessed via this->.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458