Keep pointers between class members stable when moving

Viewed 100

Suppose a class C has two members, M1 and M2, where M1 holds a pointer P that refers to M2. For every instance X of C the following invariant should hold: X.M1.P points to X.M2.

Is there an idiomatic way to implement this behaviour in C++ without having to implement a move constructor and assignment operator?

I'm asking because it seems to me that conceptually the pointer P should be relative to M1. Non-default move constructors and assignment operators seem like lots of work (especially if there are a few members) for this simple concept.

My specific use-case is similar to the example below (where set is M1, and less is M2). Perhaps my fundamental approach is flawed — is there a better way than having a pointer to Relation in Less?

using Relation = std::vector<std::vector<bool>>;

class C {
 public:
  C() { /* less = ...; */ }
  C(C&&) = default;
  C& operator=(C&&) = default;

 private:
  struct Less {
    explicit Less(const Relation* r) : r(r) {}
    bool operator()(int i, int j) { return (*r)[i][j]; }
    const Relation* r;
  };

  Relation less;
  std::set<int, Less> set{Less(&less)};
};

C a;
std::cout << a.set.key_comp().r == &a.less << std::endl; // true
C b = std::move(a);
std::cout << b.set.key_comp().r == &b.less << std::endl; // false
0 Answers
Related