1

According to Does std::atomic<std::string> work appropriately?, std::atomic<std::string> is not valid and may lead to undefined behaviour.

What about std::atomic<std::optional<std::chrono::time_point<std::chrono::system_clock>>>?

std::optional has the operator= but std::chrono::time_point does not, so I'm confued. How do I know for sure for any type?

Gatonito
  • 1,662
  • 5
  • 26
  • 55
  • AFAIK `std::optional` is trivially copyable only when type it is holding is trivially copyable and `time_point` is trivially copyable. – Marek R Feb 14 '21 at 21:41

2 Answers2

6

As mentioned in the linked thread, std::atomic<T> requires T to be trivially copyable.

Here T is std::optional<U> for some U. The std::optional class template forwards triviality: its copy constructor, move constructor, copy assignment operator, move assignment operator, and destructor are each trivial if the same is trivial for U.

There is no ironclad guarantee that std::chrono::time_point<std::chrono::system_clock> is trivially copyable. The underlying representation of the time_point may be an arithmetic type or "a class emulating an arithmetic type" ([time.duration]/2), which I read as being sufficiently flexible to permit e.g. nontrivial copy constructors (even if they have the same semantics as a trivial copy constructor). If that's the case, the time_point will not be trivially copyable.

In any case, std::atomic<std::optional<std::chrono::time_point<std::chrono::system_clock>>> is safe to use if it compiles. The compiler must issue a diagnostic if the T in std::atomic<T> is not trivially copyable, since the standard says "The program is ill-formed" if this condition is not met ([atomics.types.generic]/1). In previous versions of the standard, the wording was "... shall be trivially copyable", which is also a diagnosable rule since it doesn't say "otherwise the behavior is undefined" or anything similar.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
5

It's simple to check:

static_assert(std::is_trivially_copyable_v<
    std::optional<std::chrono::time_point<std::chrono::system_clock>>>);

Before gcc 8.1 (and the associated libstdc++) the assert fails so it's not safe to use. After gcc 8.1 the assert passes so it's safe.

Before clang 7 (and the asosciated libc++) the assert fails so it's not safe to use. After clang 7 the assert passes and it's safe.

bolov
  • 72,283
  • 15
  • 145
  • 224