lundi 7 janvier 2019

Constexpr on member function pointer value - undefined behavior?

I have a problem with a simple reflection like mechanism in C++. I would like to have one template type, which should behave differently with different member function pointers as template arguments:

If I have a class template with a class type and its member function pointer, I cannot specialize partially to the member pointer being null, because I cannot specialize "non-type template argument with dependent type" (see: https://en.cppreference.com/w/cpp/language/partial_specialization argument list [5])

template<class O, void(O::*foo)() = nullptr>
struct p
{};

template<class O, void(O::*foo)()>
struct p<O, nullptr>
{};

If I try to specialize to a deduced constexpr value, which reflects to the member pointer, I have different problems with the compilers. GCC8.2 x64 tells me that the nullptr == foo expression is not constant in the context: p<A, &A::f> j;. However ARM GCC8 says it is okay. I think it is some memory layout problem, that struct A is not complete at the time the template engine tries to evaluate a concrete function pointer.

template<class O, void(O::*foo)() = nullptr, bool = nullptr == foo>
struct p
{};

template<class O, void(O::*foo)()>
struct p<O, foo, true>
{};

struct A
{
    void f();
    p<A, &A::f> j;
};

It is strange that MSVC 19.5 x86 is okay with the above, it has another problem. It is working, while struct A is standalone, or it inherits from one struct. But when there are two base structs (X, Y), it dies with internal compiler error.

template<class O, void(O::*foo)() = nullptr, bool = nullptr == foo>
struct p
{};

template<class O, void(O::*foo)()>
struct p<O, foo, true>
{};

struct X{};
struct Y{};

struct A : X, Y
{
    void f();
    p<A> i;
    p<A, &A::f> j;
};

Clang7 works with all the above well.

Can anyone explain, if this is an undefined behavior, or is there any guide about this topic in the standard?

Aucun commentaire:

Enregistrer un commentaire