To use a name from dependent base class in derived class template (e.g. B<T>
), one has to add a prefix highlighting to the compiler that is a dependent name (B<T>::
). And to avoid doing it many times, a using-declaration can be used instead.
Below code with such using-declaration:
template <class T>
struct A {
constexpr static int x = 0;
};
template <class T>
struct B : A<T> {
// ok everywhere
constexpr static int y = B<T>::x;
// ok in MSVC
using B<T>::x;
constexpr static int z = x;
};
is found to work fine in MSVC compiler, while others do not like it. Clang in particular complains
error: no member named 'x' in 'B'
Hovewer Clang does not see any error in y = B<T>::x
one line above. Online demo: https://gcc.godbolt.org/z/PvKW753M8
Which implementation is correct here and why?
The program is IFNDR (ill-formed, no diagnostic required).
This is because you never instantiate any specialization, but every instantiation of a specialization of B
would be ill-formed. See [temp.res.general]/6.1.
Every instantiation would be ill-formed because B<T>
names the current instantiation, i.e. the current class, not a base class of it, but the left-hand side of the nested-name-specifier in a using
declaration in a class scope must name a base of the current class (or the whole name must name an enumerator). See [namespace.udecl]/3.