Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we refer to member variables in a noexcept specification?

Please consider the following code snippet:

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;
}

Is the use of the member variable m_elements inside the noexcept specifier legal? GCC 5.2 (C++17) yields the compiler error m_elements was not declared in this scope. while clang 3.6 (C++17) compiles without any error.

Both compilers yield no error if I use noexcept(std::declval<Tuple const&>().size()) instead. However, as you can see, I've created a simple example class tuple where it's crucial whether or not Tuple has qualified overloads of size.

From my point of view, it's more intuitive to write noexcept(m_elements.size()) cause it's exactly the call in the function body and it takes into account that the size method of vector is const qualified (which makes m_elements a const object in the scope of the function).

So, what's the legal usage? If both are equivalent, which should I use? Should I use noexcept qualifiers at all in this scenario? The problem is that whether or not the vector functions will throw depends in all most every case on Tuple.

like image 488
0xbadf00d Avatar asked Mar 08 '16 15:03

0xbadf00d


People also ask

Which of the following are valid reasons for using the C++ keyword Noexcept?

The noexcept specification is part of the function type but can not be used for function overloading. There are two good reasons for the use of noexcept: First, an exception specifier documents the behaviour of the function. If a function is specified as noexcept, it can be safely used in a non-throwing function.

What's the point of Noexcept?

The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.

When should you use Noexcept C++?

The dynamic exception specification, or throw(optional_type_list) specification, was deprecated in C++11 and removed in C++17, except for throw() , which is an alias for noexcept(true) . We recommended you apply noexcept to any function that never allows an exception to propagate up the call stack.

Can a constructor be Noexcept?

Inheriting constructors and the implicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, move-assignment operators are all noexcept(true) by default, unless they are required to call a function that is noexcept(false) , in which case these functions are ...


1 Answers

Clang is correct here, this is gcc bug 52869. According to [basic.scope.class], emphasis mine:

The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration, but also of all function bodies, default arguments, exception-specifications, and brace-or-equal-initializers of non-static data members in that class (including such things in nested classes).

The scope of m_elements includes the noexcept-specification for size().

like image 192
Barry Avatar answered Oct 15 '22 02:10

Barry