https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83596
Bug ID: 83596 Summary: ['17] can't use member pointer result of a constexpr function as template argument Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: oremanj at mit dot edu Target Milestone: --- The below C++ program defines a constexpr function that returns a pointer-to-member, then attempts to use that pointer-to-member as a template argument. I believe this is fine by the standard, and clang (5.0.0) accepts it, but gcc complains, in a fashion that suggests there's some internal confusion about types going on. $ cat t.cc struct X { int x; int y; }; template <int X::* mp> int get(X& x) { return x.*mp; } constexpr int X::* getMP() { return &X::y; } constexpr int X::* mptr = getMP(); int test() { X x{1, 2}; return get<mptr>(x); } $ g++ -std=c++17 -c t.cc t.cc: In function 'int test()': t.cc:7:23: error: no matching function for call to 'get<mptr>(X&)' return get<mptr>(x); ^ t.cc:2:28: note: candidate: template<int X::* mp> int get(X&) template <int X::* mp> int get(X& x) { return x.*mp; } ^~~ t.cc:2:28: note: template argument deduction/substitution failed: t.cc:7:23: error: '4' is not a valid template argument for type 'int X::*' return get<mptr>(x); ^ t.cc:7:23: note: it must be a pointer-to-member of the form '&X::Y' $ g++ --version g++ (GCC-Explorer-Build) 8.0.0 20171226 (experimental) Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The error is unchanged under any of the following perturbations: - every 'int X::*' is replaced by 'auto' - the result of getMP() is passed as the template argument directly - mptr is defined as &X::y directly, getMP() is defined to return mptr, and get() is instantiated with <getMP()> as its argument - optimizations are used or not used - either getMP() or mptr is assigned to a local-scope constexpr in test() which is then used as the template argument Compilation succeeds if there is no constexpr function involved, e.g. if the source file says 'constexpr int X::* mptr = &X::y;' directly. gcc 7.2.1 returns a slightly different error message; the final "note:" above is replaced with t.cc:7:23: error: it must be a pointer-to-member of the form '&X::Y' t.cc:7:23: error: could not convert template argument 'mptr' from 'int X::* const' to 'int X::*'