I've a setup where I need to exchange data provided in structs between two modules .
Module 1 provides data in a shared_ptr of a struct, while module 2 needs data in a "normal" struct.
Code:
#include <iostream>
#include <memory>
#include <cstring>
struct MyStruct1 {
int x;
double y;
long long z;
};
struct MyStruct2 {
int x;
double y;
long long z;
};
int main() {
auto one = std::shared_ptr<MyStruct1>(new MyStruct1());
MyStruct2 two;
one->x = 10;
one->y = 3.141;
one->z = 1e9;
std::cout << "Size of one: " << sizeof(one) << "\n"; // Size of one: 16
std::cout << "Size of *one: " << sizeof(*one) << "\n"; // Size of *one: 24
std::cout << "Size of two: " << sizeof(two) << "\n"; // Size of two: 24
memcpy(&two, &(*one), sizeof(two));
std::cout << "two.x: " << two.x << "\n"; // two.x: 10
std::cout << "two.y: " << two.y << "\n"; // two.y: 3.141
std::cout << "two.z: " << two.z << "\n"; // two.z: 1000000000
return 0;
}
My project setup guarantees that both structs are defined exactly the same. Therefore, I make use of memcpy
.
Since one is a (shared) pointer I tried to use it directly in the command
memcpy(&two, one, sizeof(two));
which results in the error no suitable conversion function from std::shared_ptr<MyStruct1>" to "const void *" exists
.
As you see, I circumvent this by de-referincing and then making a normal pointer. While this seems to work, it looks like a hard misuse.
Therefore, I'd kindly ask for your advice on how to copy data properly in this setup.
- Is there a better way than memcpy?
- How to address source and target properly?
- What needs to be considered in terms of efficiency (speed, memory usage)?
This is a simplified example. In real application, module 1 is a ros2 message callback, which has an interface like void topic_callback(const pck::msg::msg1::SharedPtr msg) const
Additionally, the structs in my real application are nested with huge number of elements.
I do have an assertion, which double-checks that size of source and target are actually the same
CodePudding user response:
By using same type for different objects assignment operator overloading can also copy content from one object to the other. I know you are trying to copy different types, maybe operator overloading for each type can be beneficial. By the way be aware of precision lost by copying elements for example first element of MyStruct1 can be float and the second type maybe integer.
Actually, my considiration here is copying obejcts of two different types can be tedious and error prone in the future even if size of two types are same.
After an update, here the solution i found. With this way you also check the types of other members.
struct MyStruct1 {
int x;
double y;
long long z;
MyStruct1& operator=(const MyStruct2& a) {
x = a.x;
y = a.y;
z = a.z;
return *this;
}
};
Note: :Since second type should be treated first it should be located above the first data type like:
struct MyStruct2 {
float x;
double y;
long long z;
};
struct MyStruct1 {
float x;
double y;
long long z;
MyStruct1& operator=(const MyStruct2& a)
{
x = a.x;
y = a.y;
z = a.z;
return *this;
}
};
And the usage of the assignment look as simple as like that in the main:
two = *one;
instead of this
memcpy(&two, &(*one), sizeof(two));