Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it abuse to deduce parameters of parent template when passing pointer to constexpr function in the scope of a class

Minimal example I got is a bit 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 problem, [clang] complains about matching Parent against Kid problem:

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

To get 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 the code. So... is it a bug or am I starting to go insane?

like image 801
W.F. Avatar asked Dec 17 '17 11:12

W.F.


1 Answers

Clang is right to the letter of the law. Yes, Kid is derived from Parent. But that relationship can only be established once Kid is a completely defined type. And well, [class.mem]/6:

A class is considered a completely-defined object type ([basic.types]) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, noexcept-specifiers, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

We are in the "otherwise" part I highlighted. Even though we are dealing with pointers, the class is not yet considered defined for the pointer conversion to be valid. GCC is overly permissive.

like image 188
StoryTeller - Unslander Monica Avatar answered Oct 26 '22 22:10

StoryTeller - Unslander Monica