Is there an abuse of the output of the parameters of the parent template when passing a pointer to the constexpr function in the class class

The minimal example I got is a bit more complicated:

struct A { }; template <int> struct Parent { }; template <int N> constexpr int operator*(A, Parent<N>*) { return N; } template <class T> using ptr = T*; template <int> struct Other { }; template <int N> struct Kid: Parent<N> { static Other<A{} * ptr<Kid>{}> o; }; int main() { Kid<2>{}; } 

[gcc] compiles the code without any problems, [clang] complains about matching the Parent problem with Kid :

 prog.cc:7:15: note: candidate template ignored: could not match 'Parent' against 'Kid' constexpr int operator*(A, Parent<N>*) { return N; } 

To become more absurd when we change the code a bit:

 struct A { }; template <int> struct Parent { }; template <int N> constexpr int operator*(A, Parent<N>*) { return N; } template <class T> using ptr = T*; template <int> struct Other { }; template <int N> struct Kid: Parent<N> { static constexpr int s = A{} * ptr<Kid>{}; }; int main() { Other<Kid<2>::s>{}; } 

[clang] also compiles code. So ... is this a mistake, or am I starting to go crazy?

+8
c ++ language-lawyer constexpr incomplete-type template-deduction
source share
1 answer

Klang is entitled to the letter of the law. Yes, Kid is derived from Parent . But this connection can only be established after Kid is a fully defined type. And well, [class.mem] / 6 :

A class is considered a fully-defined type of an object ([basic.types]) (or a full type) when closing} the class specifier. Within a class, a class is considered complete within functional bodies, default arguments, noexcept-specificers, and default element initializers (including such things in nested classes). Otherwise, it is considered incomplete in its class member specification.

We are in the β€œother” part that I have highlighted. Despite the fact that we are dealing with pointers, the class is not yet considered defined so that the pointer transformation is valid. GCC is overly permissive.

+6
source share

All Articles