Search code examples
c++c++-chronostdatomic

Why can't a std::atomic of a std::chrono time_point member variable be default constructed?


I have an atomic wrapping a chrono time_point value. The default construction of time_point is fine for me, so I expect to not need to explicitly set it. However in gcc I get a compiler error without explicitly setting the default. Here's a minimal example:

#include <atomic>
#include <chrono>

struct A
{
    using TimePoint = std::chrono::system_clock::time_point;
    std::atomic<TimePoint> point;
};

int 
main()
{
    A a;
    return 0;
}

Here's the error message:

<source>: In function 'int main()':
<source>:13:7: error: use of deleted function 'A::A()'
     A a;
       ^
<source>:6:5: note: 'A::A()' is implicitly deleted because the default definition would be ill-formed:
     A() = default;
     ^
<source>:6:5: error: use of deleted function 'constexpr std::atomic<_Tp>::atomic() [with _Tp = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >]'
In file included from <source>:1:
/opt/compiler-explorer/gcc-8.3.0/include/c++/8.3.0/atomic:194:7: note: 'constexpr std::atomic<_Tp>::atomic() noexcept [with _Tp = std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1, 1000000000> > >]' is implicitly deleted because its exception-specification does not match the implicit exception-specification ''
       atomic() noexcept = default;
       ^~~~~~
Compiler returned: 1

Here's a godbolt link: https://godbolt.org/z/YocxGd

I can work around this by simply explicitly adding a default initialization (https://godbolt.org/z/8z5WqW):

std::atomic<TimePoint> point{TimePoint{}};

But it seems silly that I would need to do that. I don't understand what is wrong. I notice that clang and gcc starting with 10.x don't complain about the implicit default. Is this just a compiler bug with the older versions of gcc? Or is there a more elegant way I should handle this than the explicit default initialization of time_point?


Note that std::atomic<std::chrono::high_resolution_clock::time_point> can not compile references this same error message but is asking about (and gets answers for) the mechanics of sharing the time_point between threads. I'm not having a problem with that. I'm asking particularly about why the implicit default constructed value isn't working when the explicit default constructed value does work.


Solution

  • Nice answer @Nicol - but I'm going to go with a libstdc++ bug. The following code:

    #include <atomic>
    
    struct A {
        A() {}
    };
    
    int main () {
        std::atomic<A> a;
    }
    

    gives a similar error on gcc 8.3/9.x, but compiles w/o error on gcc 10.x (all with -std=c++17)

    clang8 + libstdc++ 8.3 fails as well.

    clang + libc++ compile w/o error.