请考虑以下代码段:
template<class Tuple>
class vector
{
public:
typename Tuple::size_type size() const noexcept(noexcept(m_elements.size())) {
return m_elements.size();
}
private:
Tuple m_elements;
};
class tuple
{
public:
using size_type = std::size_t;
size_type size() const { return 0; }
size_type size() noexcept { return 0; }
};
int main()
{
vector<tuple> x;
static_assert(noexcept(x.size()), "x.size() might throw");
return 0;
}
m_elements
说明符中成员变量noexcept
的使用是否合法? GCC 5.2 (C++17) yields the compiler error m_elements
未在此范围内声明。而clang 3.6 (C++17) compiles without any error。
如果我改用noexcept(std::declval<Tuple const&>().size())
,两个编译器都不会产生错误。但是,正如您所看到的,我已经创建了一个简单的示例类tuple
,无论Tuple
是否具有size
的限定重载,它都至关重要。
从我的观点来看,编写noexcept(m_elements.size())
更直观,因为它恰好是函数体中的调用,并且它考虑了size
方法vector
是const
限定的(使m_elements
成为函数范围内的const对象。)
那么,合法用法是什么?如果两者都是等价的,我应该使用哪一个?在这种情况下我应该使用noexcept
限定词吗?问题在于vector
函数是否会抛出,取决于Tuple
的所有情况。
答案 0 :(得分:7)
Clang在这里是正确的,这是gcc bug 52869。根据{{3}},强调我的:
在类中声明的名称的潜在范围不仅包括后面的声明性区域 name的声明,但也包括该类中非静态数据成员的所有函数体,默认参数, exception-specifications 和 brace-or-equal-initializers (包括嵌套的这类东西 类)。
m_elements
的范围包括size()
的 noexcept-specification 。