If you turn up your warning level to -Wall
, GCC 8 (at least g++ (Ubuntu 8.3.0-6ubuntu1~18.10.1) 8.3.0
with --std=c++17
) gives -Wclass-memaccess
on:
#ifdef __cplusplus
#include <type_traits>
#endif
#include <string.h>
struct CantCopy {
int i;
#ifdef __cplusplus
CantCopy () = default;
CantCopy (const CantCopy &other) = delete;
void operator= (const CantCopy &rhs) = delete;
#endif
};
int main(int argc, char *argv[]) {
#ifdef __cplusplus
static_assert(std::is_pod<CantCopy>::value);
#endif
struct CantCopy src;
src.i = 1020;
struct CantCopy dest;
memcpy(&dest, &src, sizeof(struct CantCopy));
return 0;
}
The warning says:
warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of type ‘struct CantCopy’ with no trivial copy-assignment [-Wclass-memaccess]
memcpy(&dest, &src, sizeof(CantCopy));
What I have is code that's intended to build as either C or C++. But the C++ build is supposed to be able to statically check when C programmers are going through direct assignments of the structure--when they should be using a function. Hence disabling copying.
But it's still POD, and all this does was delete the operators. I can see the scenario this warning is designed to help with, but this isn't that situation.
Is there any easy way to do something equivalent to this without needing to disable the warning?
It seems that you could achieve your aim to make assignments and copies in C++ outside of a designated function impossible better by making the assignment operator and copy constructor default and private and adding your Move_Value(&cantcopy_dest, &cantcopy_src)
as a friend.
struct CantCopy;
#ifdef __cplusplus
extern "C" {
#endif
void Move_Value(CantCopy *cantcopy_dest, const CantCopy *cantcopy_src);
#ifdef __cplusplus
} // extern "C"
#endif
struct CantCopy {
int i;
#ifdef __cplusplus
CantCopy () = default;
private:
CantCopy (const CantCopy &other) = default;
constexpr CantCopy &operator= (const CantCopy &rhs) = default;
friend void Move_Value(CantCopy *cantcopy_dest, const CantCopy *cantcopy_src);
#endif
};
struct Other
{
CantCopy c;
};
void test()
{
CantCopy c1;
CantCopy c2;
// fails: c3{c1};
// fails: c2 = c1;
Move_Value(&c1, &c2);
Other o;
Other o2;
// also fails: o = o2;
}
void Move_Value(CantCopy *cantcopy_dest, const CantCopy *cantcopy_src)
{
// do special stuff
*cantcopy_dest = *cantcopy_src;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With