如何使用 std::function 复制 "partially" 对象?

How to copy "partially" an object using a std::function?

这是 code 我有:

#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;
}

但错误越来越多。

我只需要复制对象的一部分 "part"。 这只是一个测试,当然真正的对象有很多成员字段,有些需要忽略。

如何在 std::function<Buffer()> 内完成?

好的,因为问题可能并不明显:

  1. 复制赋值运算符通常应该有一个 const& 参数,而不是 & 参数。

  2. 然后您还应该提供 Envelope 的复制构造函数,如您所示。首先,它的行为不同于隐式生成的行为(它将复制所有元素,而不仅仅是 y),并且当存在用户定义的复制赋值时隐式复制构造函数的生成已被弃用从 C++11 开始,可能会在未来的标准迭代中删除。

  3. 那么你还需要默认默认构造函数,因为你现在有一个用户定义的构造函数:

    Envelope() = default;
    
  4. 此外,您的复制赋值运算符被声明为 return a Envelope&(应该如此),但您忘记实际放入 return 语句它在最后,所以执行它会导致未定义的行为:

    return *this;
    

您可以创建自己的副本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();
}