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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With