Reference as a non-type template argument

前端 未结 1 1024
迷失自我
迷失自我 2021-02-07 06:35

The example below attempts to use a variable of reference type as an argument for a non-type template parameter (itself of reference type). Clang, GCC and VC++ all reject it. Bu

1条回答
  •  无人共我
    2021-02-07 07:11

    Introduction

    It is correct saying that the name of a reference is an id-expression, though; the id-expression doesn't refer to whatever the reference is referencing, but the reference itself.

     int    a = 0;
     int& ref = a; // "ref" is an id-expression, referring to `ref` - not `a`
    

    The Standard (N4140)

    You are quoting the relevant sections of the standard in your post, but you left out the most important part (emphasize mine):

    14.3.2p1 Template non-type arguments [temp.arg.nontype]

    A template-argument for a non-type, non-template template-parameter shall be one of:

    • ...

    • a constant expression (5.19) that designates the address of a complete object with static sturage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; ...


    Note: In earlier drafts "where id-expression is the name of an object or function" isn't present; it was addressed by DR 1570 - which undoubtedly makes the intent more clear.


    A variable of reference type is not an object?

    You are absolutely correct; the reference itself has reference type, and can merely act as an object when part of an expression.

    5p5 Expressions [expr]

    If an expression initially has the type "reference to T" (8.3.2, 8.5.3), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.


    Elaboration

    It is very important to note that the constant expression ("that designates the address of a complete object...") must be one of &id-expression, or id-expression.

    Even though a constant-expression, that isn't just an id-expression, might refer to an object with static storage duration, we cannot use it to "initialize" a template-parameter of reference- or pointer type.

    Example Snippet

    template
    struct A { };
    
    int            a = 0;
    constexpr int& b = (0, a); // ok, constant-expression
    A<(0, a)>      c = {};     // ill-formed, `(0, a)` is not an id-expression
    

    Note: This is also a reason behind the fact that we cannot use string-literals as template-arguments; they are not id-expressions.

    0 讨论(0)
提交回复
热议问题