Constexpr is not allowed in declaration of friend template specialization?

GCC is wrong here.

All references are to N4431, the latest C++ WD.

[tl;dr: There’s a difference between a function being inline (or more precisely, being an inline function, as defined in 7.1.2/2) and being declared with the inline specifier. The constexpr specifier makes a function inline, but isn’t an inline specifier.]

Specifiers are described in subclause 7.1 of the C++ standard, and are an element of the grammar. Therefore, whenever standard talks about a foo specifier appearing somewhere, it means that specifier literally appeared within the (parse tree of the) source code. The inline specifier is a function-specifier, described in subclause 7.1.2, and its effect is to make a function be an inline function. (7.1.2)/2:

A function declaration (8.3.5, 9.3, 11.3) with an inline specifier declares an inline function.

There are two other ways to declare an inline function, without using an inline specifier. One is described in (7.1.2)/3:

A function defined within a class definition is an inline function.

The other is described in (7.1.5)/1:

constexpr functions and constexpr constructors are implicitly
inline (7.1.2).

Neither of these says that the behavior is as if an inline specifier were present, merely that the function is an inline function.

So why does this rule exist?

There’s a simpler form of this rule in (7.1.2)/3:

If the inline specifier is used in a friend declaration, that declaration shall be a definition or the function shall have previously been declared inline.

The purpose of this is to allow friend declarations to be ignored in most cases — they are not permitted to add “new information” to the befriended entity, except in the special case where they are defining a friend function. (This in turn allows an implementation to delay parsing a class definition until it’s “needed”.) Thus we also see, in (8.3.6)/4:

If a friend declaration specifies a default argument expression, that declaration shall be a definition and shall be the only declaration of the function or function template in the translation unit.

And the same applies to a declaration of a friend specialization of a function template: if it could add extra information, then implementations could not delay parsing the class definition.

Now, note that this rationale does not apply to constexpr: if the constexpr specifier appears on any declaration of a function, it must appear on every declaration, per (7.1.5)/1. Since there is no “new information” here, there is no need for a restriction.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)