Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should constructors on std::chrono::...::time_point be noexcept? (Or why aren't they?)

I encountered this problem trying to hold on to an atomic time_point, see (atomic requires noexcept default constructor if default constructor available): http://cplusplus.github.io/LWG/lwg-active.html#2165

The simple problem is std::atomic or similar will fail to compile under the current std.

Considering the std::chrono::clock_type::now() s are noexcept. It seems bizarre that the timepoints themselves are not.

like image 555
amurray Avatar asked Mar 27 '14 23:03

amurray


1 Answers

In my humble opinion, they should be conditionally noexcept. And to describe the correct condition, we need to back up and discuss the constructors of duration.

First the special constructors: default and copy.

These constructors are correctly specified with = default. That means that if the underlying rep has special noexcept constructors then the duration will too. That is exactly what we want.

Now what about:

template <class Rep2>
   constexpr explicit duration(const Rep2& r);
template <class Rep2, class Period2>
   constexpr duration(const duration<Rep2, Period2>& d);

These are not currently noexcept, but we would like for them to be if the constructions that they call are noexcept. For example:

template <class Rep2>
   constexpr explicit duration(const Rep2& r)
       noexcept(is_nothrow_constructible<rep, Rep2 const&>{});
template <class Rep2, class Period2>
   constexpr duration(const duration<Rep2, Period2>& d)
       noexcept(noexcept(is_nothrow_copy_constructible<rep>{}) &&
                noexcept(std::chrono::duration_cast<duration>(d)));

This means that they will be noexcept for the common use cases. However if you create a Rep that is an arithmetic emulator that might (for example) throw on overflow, then these constructors will correctly not be noexcept.

To make these constructors actually work, the member function count() needs to be conditionally noexcept, and the function duration_cast needs to be made conditionally noexcept.

Now (and only now) one can start to tackle the time_point constructors with similar rigor.

This is all doable. I've just prototyped it to confirm that I'm actually giving good information in this answer. However to make this all std, one has to:

  1. Implement and fully test the whole thing.
  2. Write a proposal that convincingly argues that this is implementable, and valuable to the clients.
  3. Attend standards meetings and present this proposal, and be convincing.
  4. When the committee finds holes in your argument (and they will), fix the implementation, fix the proposal, and go back to step 3.
  5. Continue with steps 3 and 4 until the committee is so sick of hearing from you that they give in and vote it into a draft standard.
  6. Wait for the draft to become an official standard, and protect the proposal from being voted out of the standard while waiting.

To date the committee has applied conditional noexcept to functions exceedingly sparingly.

The answer to the question in the title is simply:

No one has put all this work into it. However I would encourage people to do so. I believe this would benefit the clients of <chrono>.

like image 177
Howard Hinnant Avatar answered Nov 09 '22 12:11

Howard Hinnant