p0lAris
p0lAris

Reputation: 4820

Reset struct values in C++11

Looks like this question has been asked a few times but I can't seem to get it working based on existing answers and guidance.

Here's the code:

#include <atomic>

class X
{
  public:
    X();
    ~X();
    void alpha();
  private:
    struct A {
      bool m;
      std::atomic<bool> n;
      bool fish();
    };
    A aval_;
};

X::X() : aval_() {}
X::~X() {}

bool X::A::fish() {
  return true;
}

void X::alpha() {
  aval_.m = false;
  aval_ = {};
}

Object of type 'X::A' cannot be assigned because its copy assignment operator is implicitly deleted

Should I be overriding something? I am not generally a C++ programmer so feel free to point me to resources where I can learn more.

EDIT: Updated the source code to include std::atomic<bool>.

Upvotes: 2

Views: 442

Answers (1)

Constantinos Glynos
Constantinos Glynos

Reputation: 3186

The reason is because std::atomic does not have a default copy-constructor. Try the following code:

std::atomic<bool> v1(false);
std::atomic<bool> v2  = v1;

The errors you should get are:

error: call to implicitly-deleted copy constructor of 'std::atomic<bool>'
    std::atomic<bool> n2  = n1;
                      ^     ~~
note: copy constructor of 'atomic<bool>' is implicitly deleted because base class '__atomic_base<bool>' has a deleted copy constructor

note: '__atomic_base' has been explicitly marked deleted here
    __atomic_base(const __atomic_base&) = delete;

If the sole purpose of this is to reset the members of A, then simply create a reset function void reset() and reset the members to their initial values.

void reset()
{
    m = false;
    n = false;
}

and then in void alpha() do:

void alpha()
{
    aval.m = false;
    aval.reset();
}

The above is Plan A. As Plan B, you can use a smart pointer (std::unique_ptr) to hold aval. Then you can simply reset the pointer.

So instead of using the stack:

A aval;

You use the heap:

    ...
    std::unique_ptr<A> aval;

public:
    X() : aval(std::make_unique<A>())
    {;}

    void alpha()
    {
        aval->m = false;
        aval.reset(new A());
    }

I personally like the first approach. Consider the fact that, regardless of its' name "constructor", a constructor constructs nothing. All it does is initialize the members of the class. That's exactly what the reset() does, and you use the stack.

Upvotes: 2

Related Questions