This code is accepted by GCC (several versions) and refused by clang (also several versions):
struct ACS{};
template<typename Dep>
struct AD{};
template<typename Der, typename Dep>
struct PA{
explicit PA(ACS&) {}
};
template<typename AT, typename ADep>
struct AA : public PA< AA<AT, ADep>, AD<ADep> >
{
using base = PA< AA<AT, ADep>, AD<ADep> >;
using base::PA;
// accepted by both: using base::base;
};
int main()
{
ACS acs;
AA<int, double> aa{acs};
}
To me, this looks like the same situation as clang doesn't see base class constructors pulled in via typedef. However, instead of a "no matching constructor" error message, clang issues this error message:
<source>:15:17: error: dependent using declaration resolved to type without 'typename'
using base::PA;
^
Apparently, clang expects the typename keyword. The hint suggests adding it before PA, but this:
using base:: typename PA;
is silly, and is rejected by both compilers. However, the more sensible alternative:
using typename base::PA;
is accepted without a syntax error, but now clang complains:
<source>:22:21: error: no matching constructor for initialization of 'AA<int, double>'
AA<int, double> aa{acs};
^ ~~~~~
In contrast, using base::base is accepted by both compilers, even without a typename. In fact, using typename base::base is accepted only by GCC; clang complains:
<source>:18:27: error: typename is allowed for identifiers only
using typename base::base;
~~~~~~~~~ ^
What's going on? Why is using base::PA different from using base::base? Isn't base an alias of PA?
using PA<AA<AT, ADep>, AD<ADep>>::PA;?typenamein front of the type; then clang complains).baseisusing base = AA::PA;. You can also writeusing AA::PA::PA;- both are accepted by clang.using base = AA::PAmay be shorter, but it's ill-formed:invalid use of incomplete type 'struct AA<AT, ADep>'godbolt.org/z/r5q68MTjq