12

Does C++11 give any guarantees about inline functions or methods, when they make calls to other functions declared with the noexcept qualifier?

class My_String { ...

    const char * c_str () const noexcept;
    inline operator const char * () const { return c_str(); }
};

I assume an optimizing compiler would be free to implement the inline method without full EH and stack unwinding, as per the noexcept qualification. I would also expect this for a simple accessor method too:

... inline operator const char * () const { return m_buffer; }

While this example looks trivial, exception guarantees matter when used to implement other classes or functions. Q: Does the C++11 standard address this or should inline methods be marked noexcept? Or is it better to omit noexcept unless required to match a class or function specification?

Edit: To avoid some confusion: Is noexcept implicit for the inline method?

Brett Hale
  • 21,653
  • 2
  • 61
  • 90

1 Answers1

9

Sorry, no. The only implicit exception-specifications are

  • On destructors.
  • On other implicitly declared or explicitly defaulted special member functions: default constructors, copy and move constructors, and copy and move assignment, when not declared in a class definition, or declared with = default;.
  • On deallocation functions: operator delete and operator delete[].

[Note that for deallocation functions, an implicit exception-specification is always as if noexcept(true). For all destructors, and for special member functions which are implicitly declared or explicitly defaulted on the first declaration, the implicit exception-specification can be either noexcept(true) or noexcept(false), as determined from the exception-specifications of the corresponding special member functions of any base classes and members of class type.]

So with either example declaration, noexcept(static_cast<const char*>(std::declval<const MyString>())) must be false. Go ahead and write noexcept where it might matter.

Of course, as you noted, a compiler optimization is still allowed to notice an inline function can't throw exceptions and simplify exception handling in the caller.

aschepler
  • 70,891
  • 9
  • 107
  • 161
  • 1
    In the list of *implicit `noexcept`* you are missing that destructors that are used declared/defined are implicitly `noexcept` unless the user provided a different exception specification. This is a deviation of C++11 from C++03 behavior. That is, a user declared destructor like `T::~T() { throw 1; }` will terminate the program even if no other exception is active (note the lack of exception specification) – David Rodríguez - dribeas Aug 15 '12 at 12:37
  • 1
    Also missed in the original answer: explicitly defaulted special members act the same as if implicitly declared. – aschepler Aug 15 '12 at 12:46
  • 1
    Also, while I understand what you are saying (and agree) I am not sure if this is going to be all so clear for readers that don't already *know* it. Implicitly declared member functions will not be *always* implicitly `noexcept`. The compiler must generate the exception specification from the definition of the members. That is, a class that holds a member of a type whose constructor is `noexcept(false)` will have an implicitly declared destructor `noexcept(false)`. A class with a user declared destructor will also have the exception specification derived in a similar way. – David Rodríguez - dribeas Aug 15 '12 at 12:48
  • Thanks. The use of `noexcept(expr)` is something I've avoided, but it's nice to know this information is available at compile time, like the `` functionality. – Brett Hale Aug 15 '12 at 15:48
  • @DavidRodríguez-dribeas Years late, but I added a bit clarifying that implicit exception-specification does not always mean non-throwing specification. – aschepler Dec 01 '18 at 16:50