Tem*_*Rex 32 c++ templates g++ constexpr c++11
我正在将一个C++ 14- constexpr代码库从Clang 移植到最新的g ++ - 5.1.考虑以下简化的本地bitset类的代码片段,自Clang 3.3(现在差不多2年!)以来,它已经正确编译了.
#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 from this piece
};
template<std::size_t N>
constexpr bool operator==(const bitset<N>& /* lhs */, const bitset<N>& /* rhs */) noexcept
{
return true;
}
int main() {}
Run Code Online (Sandbox Code Playgroud)
活生生的例子在Wandbox.但是,g ++ - 5.1和当前的trunk版本会出错:
朋友模板专业化的声明中不允许'constexpr'
问题:这是一个已知的g ++错误还是Clang不符合最新标准?
注意:上面只使用C++ 11样式的constexpr功能,因为里面没有发生任何修改operator==,所以模板,朋友和constexpr之间似乎有些奇怪的干扰.
更新:在Bugzilla上提交错误65977.
Ric*_*ith 34
GCC在这里错了.
所有参考文献都是N4431,最新的C++ WD.
[tl; dr:函数是内联函数(或者更确切地说,是内联函数,如7.1.2/2中定义的)和使用说明inline符声明的函数.该constexpr说明符使得内联函数,但是不是一个inline符.]
说明符在C++标准的子条款7.1中描述,并且是语法的一个元素.因此,每当标准谈论foo出现在某处的说明符时,就意味着说明符字面上出现在源代码的(解析树)中.的inline说明符是一个函数说明符,在第7.1.2中描述的,其作用是使一个功能是内联函数.(7.1.2)/ 2:
带有
inline说明符的函数声明(8.3.5,9.3,11.3)声明了一个内联函数.
声明内联函数还有另外两种方法,不使用inline说明符.一个在(7.1.2)/ 3中描述:
类定义中定义的函数是内联函数.
另一个在(7.1.5)/ 1中描述:
constexpr函数和constexpr构造函数是隐式内联的(7.1.2).
这些都没有说行为好像存在inline 说明符,只是函数是内联函数.
那么为什么这个规则存在呢?
在(7.1.2)/ 3中有一个更简单的规则形式:
如果
inline在朋友声明中使用了说明符,那么该声明应该是一个定义,或者该函数应该先前已经内联声明.
这样做的目的是允许在大多数情况下忽略好友声明 - 不允许他们向友好实体添加"新信息",除非他们定义友元函数的特殊情况除外.(这反过来允许实现延迟解析类定义,直到它"需要".)因此我们也看到,在(8.3.6)/ 4中:
如果朋友声明指定了默认参数表达式,则该声明应该是一个定义,并且应该是翻译单元中函数或函数模板的唯一声明.
这同样适用于函数模板的朋友特化的声明:如果它可以添加额外的信息,那么实现不能延迟解析类定义.
现在,请注意,这个理由并不能适用于constexpr:如果constexpr符出现在函数的任何声明,它必须出现在每一个声明,每(7.1.5)/ 1.由于这里没有"新信息",因此不需要限制.
| 归档时间: |
|
| 查看次数: |
1337 次 |
| 最近记录: |