c++ - Constexpr is not allowed in declaration of friend template specialization? -
i'm porting c++14-constexpr
codebase clang latest g++-5.1. consider following reduced code snippet of home-grown bitset
class has been compiling correctly since halcyon days of clang 3.3 (almost 2 years now!)
#include <cstddef> template<std::size_t> class bitset; template<std::size_t n> constexpr bool operator==(const bitset<n>& lhs, const bitset<n>& rhs) noexcept; template<std::size_t n> class bitset { friend constexpr bool operator== <>(const bitset<n>&, const bitset<n>&) noexcept; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- error piece }; template<std::size_t n> constexpr bool operator==(const bitset<n>& /* lhs */, const bitset<n>& /* rhs */) noexcept { return true; } int main() {}
live example on wandbox. however, g++-5.1 , current trunk release give error:
'constexpr' not allowed in declaration of friend template specialization
question: known g++ bug or clang not conforming latest standard?
note: above uses c++11 style constexpr
features, since there no modifications taking place inside operator==
, seems weird interference between templates, friends , constexpr.
update: filed bug 65977 on bugzilla.
gcc wrong here.
all references n4431, latest c++ wd.
[tl;dr: there's difference between function being inline (or more precisely, being inline function, defined in 7.1.2/2) , being declared inline
specifier. constexpr
specifier makes function inline, isn't inline
specifier.]
specifiers described in subclause 7.1 of c++ standard, , element of grammar. therefore, whenever standard talks foo
specifier appearing somewhere, means specifier literally appeared within (parse tree of the) source code. inline
specifier function-specifier, described in subclause 7.1.2, , effect make function inline function. (7.1.2)/2:
a function declaration (8.3.5, 9.3, 11.3)
inline
specifier declares inline function.
there 2 other ways declare inline function, without using inline
specifier. 1 described in (7.1.2)/3:
a function defined within class definition inline function.
the other described in (7.1.5)/1:
constexpr functions , constexpr constructors implicitly inline (7.1.2).
neither of these says behavior if inline
specifier present, merely function inline function.
so why rule exist?
there's simpler form of rule in (7.1.2)/3:
if
inline
specifier used in friend declaration, declaration shall definition or function shall have been declared inline.
the purpose of allow friend declarations ignored in cases -- not permitted add "new information" befriended entity, except in special case defining friend function. (this in turn allows implementation delay parsing class definition until it's "needed".) see, in (8.3.6)/4:
if friend declaration specifies default argument expression, declaration shall definition , shall declaration of function or function template in translation unit.
and same applies declaration of friend specialization of function template: if add information, implementations not delay parsing class definition.
now, note rationale not apply constexpr
: if constexpr
specifier appears on declaration of function, must appear on every declaration, per (7.1.5)/1. since there no "new information" here, there no need restriction.
Comments
Post a Comment