https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104230
Bug ID: 104230 Summary: Non-type template arguments of reference and pointer type fail when initialized by pointer to member operator Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: anton at socialhacker dot com Target Milestone: --- I believe that GCC incorrectly rejects non-type template arguments of pointer and reference type that were generated by using the pointer to member operator. My reading of "P1907R1: Inconsistencies with non-type template parameters" [1] makes me think that these uses should be acceptable. In particular the change to "13.4.2 [temp.arg.nontype] paragraph 2" moves the restriction of passing a reference to a subobject so that it only applies to subobjects of already disallowed values (temporaries, string literals ...). And it looks like that's working when using direct member access operators, but not when using pointer to member operators. And nothing there seems to indicate how the reference or pointer is generated, so presumably any valid constant expression that generates a valid pointer or reference should be acceptable. Below is a simple test case that fails on both the trunk [2] and 11.2 [3] versions on compiler explorer. struct T { int a; int b; } t; template <int *> struct U {}; U<&t.a> u1; U<&t.b> u2; U<(&(t.*(&T::a)))> u3; // Interestingly doesn't fail, good? U<(&(t.*(&T::b)))> u4; // Fails, shouldn't fail in C++20 I believe template <int &> struct V {}; V<t.a> v1; V<t.b> v2; V<(t.*(&T::a))> v3; // Fails, shouldn't fail in C++20 I believe V<(t.*(&T::b))> v4; // Fails, shouldn't fail in C++20 I believe Both compiler version produce the same output when run with `--std=c++20 -Wall`: <source>:8:18: error: '(((int*)(& t)) + 4)' is not a valid template argument for 'int*' because it is not the address of a variable 8 | U<(&(t.*(&T::b)))> u4; | ^ <source>:14:15: error: '&(int&)(& t)' is not a valid template argument of type 'int&' because '(int&)(& t)' is not a variable 14 | V<(t.*(&T::a))> v3; | ^ <source>:15:15: error: '&(((int&)(& t)) + 4)' is not a valid template argument of type 'int&' because '(((int&)(& t)) + 4)' is not a variable 15 | V<(t.*(&T::b))> v4; | ^ [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1907r1.html [2] gcc version 12.0.1 20220125 (experimental) (Compiler-Explorer-Build-gcc-bb99171b9b0f01a46bfca2d3cbd52fc6faf6cbaa-binutils-2.36.1) [3] gcc version 11.2.0 (Compiler-Explorer-Build-gcc--binutils-2.36.1)