c++c++17language-lawyerexception-safety

Where is it prohibited for target object of std::function to throw on destruction?


Consider std::function definition:

namespace std {
  template<class> class function;       // not defined

  template<class R, class... ArgTypes>
  class function<R(ArgTypes...)> {
  public:
    /* ... */
    template<class F> function(F&&);

    /* ... */

    ~function();

    /* ... */
  };

  /* ... */
}

The destructor is not marked explicitly noexcept. This declaration is interpreted that it is not noexcept in C++14 and it is noexcept starting in C++17. Implementations seem to strengthen this and mark in noexcept in C++14 (which is allowed): https://godbolt.org/z/WPh8zs7WE

The current draft does not say much about destructor, except that it destroys target object. See [func.wrap.func.con]/31:

~function();

Effects: If *this != nullptr, destroys the target of this.

Some requirements for target object are listed in constructor parameter, [func.wrap.func.con]/8 through [func.wrap.func.con]/11. Specifically, it is Lvalue-Callable and Cpp17CopyConstructible.

However I don't see where it is specified that the target object destructor does not throw.

Is it specified anywhere?

Or is destructor of function not meant to be noexcept?


Solution

  • It's a library-wide requirement, specified in [res.on.functions]:

    In certain cases ([...], operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, this document places no requirements on the implementation.

    In particular, the effects are undefined in the following cases:

    • [...]
    • If any [...] destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.