我们可以在noexcept规范中引用成员变量吗?

0xb*_*00d 9 c++ language-lawyer noexcept c++14 c++17

请考虑以下代码段:

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;
}
Run Code Online (Sandbox Code Playgroud)

m_elements在说明noexcept符中使用成员变量是合法的吗?GCC 5.2(C++ 17)产生的编译器错误 m_elements未在此范围内声明.而clang 3.6(C++ 17)编译时没有任何错误.

如果我改用,两个编译器都不会产生错误noexcept(std::declval<Tuple const&>().size()).但是,正如您所看到的,我创建了一个简单的示例类tuple,无论是否Tuple具有合格的重载都至关重要size.

从我的角度来看,它更直观,noexcept(m_elements.size())因为它恰好是函数体中的调用,并且它考虑了size方法vector是const限定的(这使得m_elementsconst对象在函数的范围内).

那么,合法用法是什么?如果两者都是等价的,我应该使用哪一个?noexcept在这种情况下我应该使用限定符吗?问题是vector函数是否会抛出取决于所有情况Tuple.

Bar*_*rry 7

Clang在这里是正确的,这是gcc bug 52869.根据[basic.scope.class],强调我的:

在类中声明的名称的潜在范围不仅包括名称的声明点后面的声明性区域,还包括所有函数体,默认参数,异常规范和非静态的括号或等于初始化器.该类中的数据成员(包括嵌套类中的这些内容).

的范围m_elements包括noexcept规格为size().