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)

Reply via email to