Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom type in std::atomic

I've put a custom class Unit in an std::atomic. Class looked as follows with a default constructor

namespace Base
{
    template <typename T, typename R, typename D>
    class Unit
    {
    public: 
        constexpr Unit() = default;
    private:
        T m_Value;
    };
}

It used to work fine until I noticed I forgot to initialize the only member of my class to zero in the default constructor. Therefore I removed the = default and provided an implementation of the constructor

template <typename T, typename R, typename D>
constexpr Unit<T, R, D>::Unit() :
    m_Value(T(0))
{   }

Now I am getting a compiler error:

Error C2280 'std::atomic<Base::Unit>::atomic(void) noexcept': attempting to reference a deleted function

My hunch was that that's because of the fact that I now provide a custom constructor, which causes the default copy constructor to no longer be implicit defined.

So, I added this as well to the class declaration

Unit(const Unit<T, R, D>& U) = default;

However, I'm getting the same error. I'm not sure what I could be. I'm not sure which deleted function the compiler is referring to.

Any help would be appreciated

like image 812
Ben Avatar asked Oct 28 '25 17:10

Ben


2 Answers

The issue here is the exception guarantee of your type. Per this post/reference your default constructor is noexcept. When you add your own, you do not provide an exception specification so it is not noexcept. What you need to do is add that to your default constructor since std::atomic's default constructor is marked as noexcept

namespace Base
{
    template <typename T, typename R, typename D>
    class Unit
    {
    public:
        constexpr Unit() noexcept;
    private:
        T m_Value;
    };

    template <typename T, typename R, typename D>
    constexpr Unit<T, R, D>::Unit() noexcept :
        m_Value(T(0))
    {   }
}

int main() 
{
    std::atomic<Base::Unit<int, int, int>> foo;
}
like image 118
NathanOliver Avatar answered Oct 31 '25 07:10

NathanOliver


One workaround is to drop the constructor and use default member initializers:

template<class T>
struct Unit {
    T value = 0;
};

int main() {
    std::atomic<Unit<int>> a;
    std::atomic<Unit<int>> b = {{1}};
}
like image 35
Maxim Egorushkin Avatar answered Oct 31 '25 06:10

Maxim Egorushkin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!