Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit generated members and noexcept

I recently started to add the new noexcept specification to move constructors/assignments wherever possible. Now I started to wonder what the exception specification of implicit generated member functions looks like. Since having noexcept move functions allows the use of more efficient code paths(e.g. when resizing a vector) I would hope that those are declared as noexcept whenever possible. I had problems understanding what the standard has to say about that and therefore tried the following code in g++4.6 (with -std=c++0x) to get some grip on it:

struct foobar{};
int main()
{
    foobar a, b;
    std::cout<<std::boolalpha
             <<noexcept(foobar())<<", "<<noexcept(foobar(a))<<", "
             <<noexcept(a = b)   <<", "<<noexcept(a = std::move(b))<<", "
             <<noexcept(foobar(std::move(a)))<<std::endl;
}

This gave me an output of True, True, True, False, False, meaning that default and copy constructor/assignment where noexcept, while move operation where not.

Now for my question:

Under what circumstances are implicit generated (or defaulted) member functions declared as noexcept? Furthermore is the obseved behaviour for foobar correct or simply a compiler bug in gcc4.6?

like image 686
Grizzly Avatar asked Feb 07 '12 16:02

Grizzly


1 Answers

Library bug — it shows true, true, true, true, true in gcc 4.7.

And the bug is not that the generated move constructors aren't noexcept, but that std::move is not marked as noexcept, as we can see with the additional tests:

std::cout << noexcept(a = static_cast<foobar&&>(b)) << ", "  // true
          << noexcept(foobar(static_cast<foobar&&>(b))) << ", " // true
          << noexcept(std::move(b)) << std::endl;   // false

Most of the library functions in gcc 4.6 was not noexcept-correct, and this has been addressed in gcc 4.7,


As for when the implcitely generated member functions are noexcept, this is documented in §15.4/14. Basically, it is noexcept if all functions it will need to call are all noexcept.

An implicitly declared special member function (Clause 12) shall have an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f shall allow all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions if every function it directly invokes allows no exceptions.

like image 163
kennytm Avatar answered Nov 03 '22 00:11

kennytm