This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/65695] [4.9/5 Regression] NSDMI calling constexpr constructor with pointer-to-member is not a constant expression


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65695

Sebastian JÃhne <jaehnesn at gmx dot de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jaehnesn at gmx dot de

--- Comment #4 from Sebastian JÃhne <jaehnesn at gmx dot de> ---
(In reply to Jonathan Wakely from comment #0)
> From https://gcc.gnu.org/ml/gcc-help/2015-04/msg00034.html
> 
> template <typename T>
> struct Bar
> {
>     using MemberFuncT = int (T::*)();
> 
>     MemberFuncT h_;
>     constexpr Bar(MemberFuncT h) : h_{h}
>     {
>     }
> };
> 
> struct Foo
> {
>     int test()
>     {
>         return -1;
>     }
> 
>     // this causes the brace-enclosed initializer error message:
>     static constexpr Bar<Foo> bar = Bar<Foo>(&Foo::test);
> 
>     // but this line does not:
>     // static constexpr Bar<Foo> bar = Bar<Foo>(nullptr);
> 
>     // this line also causes the error message, unless you remove the
>     // explict constructor in Bar.
>     // static constexpr Bar<Foo> bar = {&Foo::test};
> };
> 
> constexpr Bar<Foo> Foo::bar;
> 
> // the line below does not cause any problems, either:
> // static constexpr Bar<Foo> bar = Bar<Foo>(&Foo::test);
> 
> int main(void)
> {
>     Foo f;
>     return (f.*(Foo::bar.h_))();
> }
> 
> c.cc:20:56: error: âBar<Foo>{&Foo::test}â is not a constant expression
>      static constexpr Bar<Foo> bar = Bar<Foo>(&Foo::test);
>                                                         ^
> 
> Clang and EDG accept the code.

If you change your code in the following manner, it works:

template <typename T>
struct Bar
{
    using MemberFuncT = int (*)();

    MemberFuncT h_;
    constexpr Bar(MemberFuncT h) : h_{h}
    {
    }
};

struct Foo
{
    static int test()
    {
        return -1;
    }

    static constexpr Bar<Foo> bar = Bar<Foo>(&Foo::test);
};

constexpr Bar<Foo> Foo::bar;

int main(void)
{
    Foo f;
    return (f.bar.h_)();
}

You shouldn't be able to declare a static variable which has access to a
non-static member function. I would call this a bug in CLANG and EDG.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]