Как "частично" скопировать объект, используя функцию std ::? - PullRequest
2 голосов
/ 08 апреля 2020

Вот код У меня есть:

#include <iostream>
#include <functional>

struct Test {
    struct Envelope {
        const int x = 1;
        int y = 2;
        int z = 3;
    };

    Envelope mEnvelope;

    struct Buffer {
        Envelope mEnvelope;
    } mBuffer;
    std::function<Buffer()> func{[this] {
        mBuffer.mEnvelope = mEnvelope;

        return mBuffer;
    }};    
};  

int main() {   
    Test test;
}

там написано:

g++ -std=c++17 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In lambda function:
main.cpp:17:29: error: use of deleted function 'Test::Envelope& Test::Envelope::operator=(const Test::Envelope&)'
   17 |         mBuffer.mEnvelope = mEnvelope;
      |                             ^~~~~~~~~
main.cpp:5:12: note: 'Test::Envelope& Test::Envelope::operator=(const Test::Envelope&)' is implicitly deleted because the default definition would be ill-formed:
    5 |     struct Envelope {
      |            ^~~~~~~~
main.cpp:5:12: error: non-static const member 'const int Test::Envelope::x', can't use default assignment operator

Я пытался использовать конструктор копирования:

Envelope(const Envelope &other) {
    y = other.y;
}

или переопределить оператор =

Envelope &operator=(Envelope &other) {
    // self-assignment guard
    if (this == &other) {
        return *this;
    }            

    y = other.y;
}

Но ошибки выросли еще больше.

Мне нужно скопировать только некоторую «часть» объекта. Это всего лишь тест, конечно, реальный объект имеет множество полей членов, и некоторые из них необходимо игнорировать.

Как это сделать в std::function<Buffer()>?

Ответы [ 2 ]

2 голосов
/ 08 апреля 2020

ОК, поскольку проблема может быть не очевидна:

  1. Оператор назначения копирования обычно должен иметь параметр const&, а не &.

  2. Затем вы должны также предоставить конструктор копирования Envelope, как вы показали. Во-первых, он ведет себя не так, как неявно сгенерированный (который будет копировать все элементы, а не только y), а генерация неявного конструктора копирования при наличии пользовательского назначения копирования считается устаревшей, поскольку C ++ 11 и, вероятно, будет удален в будущей стандартной итерации.

  3. Тогда вам нужно будет также использовать конструктор по умолчанию, так как теперь у вас есть пользовательский конструктор:

    Envelope() = default;
    
  4. Более того, ваш оператор присваивания копии объявлен как возвращающий Envelope& (как и должно быть), но вы забыли фактически вставить в него оператор return в конце, поэтому выполняете это приведет к неопределенному поведению, как:

    return *this;
    
1 голос
/ 08 апреля 2020

Вы можете создать свой собственный ctor / operator для копирования только той информации, которая вам нужна:

#include <iostream>
#include <functional>

struct Test {
    typedef struct  {
        const int x;
        int y;
        int z;
    } Envelope_t;

  public:
    Test():env({1,2,3}){}

    Test(const Test & copy):env({copy.env.x,5,copy.env.z}) {}

    Test& operator=(const Test& copy){   
      env.y=copy.env.y+7;
      env.z=copy.env.z;
      return *this;
    }

    void printValues() {
        std::cout << "x:" << env.x << "\ny:" << 
                     env.y << "\nz:" <<  env.z << "\n\n";
    }

  private:
    Envelope_t env;
};  

int main() {   
  Test original;
  original.printValues();

  Test copyCtor(original);
  copyCtor.printValues();

  Test copyOp;
  copyOp = copyCtor;
  copyOp.printValues();
}

...