Как скопировать (или поменять местами) объекты типа, который содержит элементы, которые являются ссылками или константами?

Проблема, которую я пытаюсь решить, возникает при создании контейнеров, таких как std :: vector , объектов, содержащих ссылочные и константные элементы данных:

struct Foo;

struct Bar {
  Bar (Foo & foo, int num) : foo_reference(foo), number(num) {}
private:
  Foo & foo_reference;
  const int number;
  // Mutable member data elided
};

struct Baz {
  std::vector bar_vector;
};

Это не будет работать как есть, потому что оператор присваивания по умолчанию для класса Foo не может быть построен из-за ссылочного члена foo_reference и константного члена number .

Одно из решений состоит в том, чтобы заменить foo_reference указателем и избавиться от ключевого слова const . Однако при этом теряются преимущества ссылок перед указателями, и что ] const член действительно должен быть const . Это частные члены, поэтому единственное, что может навредить, - это мой собственный код, но я выстрелил себе в ногу (или выше) своим собственным кода.

Я видел решения этой проблемы в Интернете в виде методов подкачки , которые, кажется, переполнены неопределенным поведением, основанным на чудеса reinterpret_cast и const_cast . Бывает, что эти методы действительно работают на моем компьютере. Сегодня. С одной конкретной версией одного конкретного компилятора. Завтра или с другим компилятором? Кто знает. Я не собираюсь использовать решение, основанное на неопределенном поведении.

Связанные ответы по stackoverflow:

Так есть ли способ написать метод подкачки / конструктор копирования для такого класса, который не вызывает неопределенное поведение, или я просто облажался?

Изменить
Просто чтобы это сделать ясно, я уже хорошо осведомлен об этом решении:

struct Bar {
  Bar (Foo & foo, int num) : foo_ptr(&foo), number(num) {}
private:
  Foo * foo_ptr;
  int number;
  // Mutable member data elided
};

Это явно исключает const ness number и устраняет подразумеваемую const ness of ] foo_reference . Это не то решение, которое мне нужно. Если это единственное решение, отличное от UB, пусть будет так. Я также хорошо осведомлен об этом решении:

void swap (Bar & first, Bar & second) {
    char temp[sizeof(Bar)];
    std::memcpy (temp, &first, sizeof(Bar));
    std::memcpy (&first, &second, sizeof(Bar));
    std::memcpy (&second, temp, sizeof(Bar));
}

и затем пишу оператор присваивания с использованием копирования и обмена. Это позволяет обойти проблемы с ссылками и константами, но действительно ли это UB? (По крайней мере, он не использует reinterpret_cast и const_cast .) Некоторые из исключенных изменяемых данных являются объектами, которые содержат std :: vector s, поэтому я не Не знаю, подойдет ли здесь такая мелкая копия.

10
задан Community 23 May 2017 в 12:32
поделиться