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

时间:2016-03-08 15:58:29

标签: c++ language-lawyer c++14 c++17 noexcept

请考虑以下代码段:

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方法vectorconst限定的(使m_elements成为函数范围内的const对象。)

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

1 个答案:

答案 0 :(得分:7)

Clang在这里是正确的,这是gcc bug 52869。根据{{​​3}},强调我的:

  

在类中声明的名称的潜在范围不仅包括后面的声明性区域   name的声明,但也包括该类中非静态数据成员的所有函数体,默认参数, exception-specifications brace-or-equal-initializers (包括嵌套的这类东西   类)。

m_elements的范围包括size() noexcept-specification