I've got the classes:
struct A { // has no pointer members, POD - it's fine
int a, b;
char c;
};
struct B { // has no pointer members, but not POD - it's still fine
int a, b;
std::string s;
};
struct C { // has pointer members, it's not fine
int a,b;
char* cs;
};
I need to detect in compile time if any class has the properties of struct C, i.e. has pointers as members.
Short reasoning: I need to assure a user-defined type can be safely serialized and deserialized to some buffer by copying or assignment (e.g. struct A) or by providing user-defined serialize() and deserialize() methods in the class (e.g. struct B and struct c).
If B or C do not have these methods implemented, then compilation should fail, but if A does not have the methods, then the compilation should succeed.
Update:
The solution from Check if a class has a pointer data member works only for:
struct D {
int* p; // the pointer must be named 'p'
};
This issue is a different case. Can we reopen, please?
As of C++17, this is simply not possible.
You can test for a number of traits, but there is no trait that checks data members the way you need. std::is_pod<> (which will be deprecated in C++20) is the best you can get.
You can try magic_get.
It's a C++14 TMP solution for POD refrection, and it surely has its limitations (e.g. doesn't properly support references, bit fields, etc.), but you can enumerate PODs just the way you want (statically or dynamically), and then apply the std::is_pointer trait to check each field.
Example:
#include <iostream>
#include "boost/pfr/precise.hpp"
struct C {
int a, b;
char* cs;
};
int main() {
C var;
boost::pfr::for_each_field(var, [](const auto& field, std::size_t idx) {
std::cout << "field " << idx << ": is_pointer=" << std::is_pointer<std::remove_reference_t<decltype(field)>>() << '\n';
});
}
Output:
field 0: is_pointer=0
field 1: is_pointer=0
field 2: is_pointer=1
This is an XY problem.
The user that created the class needs to provide the serialize / deserialize functions according to the interface you provide. He knows if the class should be serializabile and if so how it should be done. It's the user responsibility, not yours. All you can do on your part is to provide an easy to use interface and tools to make it easier for the user to make a class serializabile.
Checking if a type has a pointer data member doesn't solve any issue and doesn't help in the slightest. You don't know if the pointer points to something the object owns exclusively, to something shared across objects, or points to a resource not-owned.
I want to know if typecasting a member variable to object pointer is okay to do in C++?
I have a class as follows -
class Foo
{
private:
int x;
int y;
int z;
public
void func1(...);
void func2(...);
void func3(...);
}
In addition I have a 3rd party code, which has a callback as -
void callbackFunction (int *xPointer)
{
// This is what I want to do
Foo * fooPtr = (Foo*)xPointer;
if(fooPtr->y == fooPtr->z)
{
//... do something
}
}
In this code, the xPointer variable points to int x of my class object.
Now, I want to know can I somehow typecast xPointer to Foo *. In C, I typecasted the pointer to struct pointer to access other member, without any problem.
Is there any danger involving such typecast in case of C++?
If it is a problem, then how can I get pointer to object using the pointer to its member variable?
Thank You
To be able to work directly with class pointers to obtain pointers to their members you must make sure that the class is a POD type. Otherwise there could be hidden members (like a vtable) or paddings that would break any effort.
To know it you should try with std::is_pod<Foo> which is a convenience trait class that will tell you if the class has a standard layout.
In any case it sounds like you should avoid this approach, since it seems inherently unsafe. Why can't you just pass the pointer to the member variable? Eg:
Foo myFoo;
cllabackFunction(&(myFoo.x));
This doesnt entirely strike me as a thing you really want to be doing. Still,
There is the offsetof (type,member) macro, it returns the byte offset of a field within your struct. You can use that to get the base address of the object (from the address of one of its members - if you know which member) and cast that address to the correct type.
of course, its not guaranteed to work for non-PODS, although not guaranteed doesn't mean it wont work, your ok with non-portable and potentially undefined behaviour aren't you?
For several reasons, I must use a struct defined in an extern C lib. I have simplified my code in order to make it readable.
Struct defined in C Lib
extern "C" {
typedef struct {
double (*_function)(double x);
} FuncR;
}
Cpp file containing class A
Class A {
public:
A();
void foo(double x); // Cannot be static since it uses m
void bar();
private:
double m; // non-static member by nature
};
void A::bar() {
FuncR f;
f._function = &A::foo;
};
The call f._function = &A::foo; generates the following error :
error C2440 : '=' : cannot convert from 'double (__thiscall A::*)(double)' to 'double(__cdecl*)(double)'
I have been searching for answers and apparently foomust be declared static. In my case it is not possible since it has to use non-static members...
Is there any trick to solve my problem ?
No, I don't think there's a trick to "fix" this.
The method call needs a this pointer, which the function pointer can't handle.
Often you can define a static "trampoline" function to get you into a method, but that requires that the outer layers (the C code, in this case) supports passing around e.g. a void * where you can store the this pointer.
Does the FuncR struct really need to be defined/used in C code? Can you use C++-style member function pointers?
How about this?...
class A;
struct classA_MemberFuncR {
double(A::*_function)(double);
};
class A {
public:
A() : m(1.234) {};
double foo(double x) {
std::cout << "In foo(" << x << "): this="
<< (void*)this << ", m=" << m << '\n';
return m+x;
}
void bar();
private:
double m; // non-static member by nature
};
void A::bar() {
classA_MemberFuncR fm;
fm._function = &A::foo;
double result = (this->*fm._function)(4.321);
std::cout << "Result is: " << result << std::endl;
};
[Comment added at this point:] Dang. Re-read OP's original post. (Supposedly we're stuck with the C struct's non-member function pointer.)
Hmm. On GCC I tried a whole lot of casting combinations and it never let me cast M::foo's address to much of anything else, so I wrote a runtime cast function template to force it to allow me to cast anything at all to any other type I want without complaining (Everyone: Please hold off on the screams of "that's not portable!" Sure it's portable... It's just how you use it that may or may not be portable!):
/*---- In a header file somewhere... ----*/
#include <stdarg.h>
template <typename ToTy, typename FromTy>
ToTy forceCast_helper(int dummy, ...);
template <typename ToTy, typename FromTy>
inline ToTy forceCast(FromTy obj) {
// ...has nothing to do with Star Wars!
return forceCast_helper<ToTy,FromTy>(1, obj);
}
/*---- In a source file somewhere... ----*/
template <typename ToTy, typename FromTy>
ToTy forceCast_helper(int dummy, ...) {
va_list args;
va_start(args, dummy);
ToTy ret = va_arg(args, ToTy);
va_end(args);
return ret;
}
Which allowed me to compile the following code without error:
typedef double(*doubleFuncDouble_t)(double);
typedef double(A::*doubleClassAMemberfuncDouble_t)(double);
f._function = forceCast<doubleFuncDouble_t>(&A::foo);
// and then call this->foo(4.321) with it from within A::bar() as follows...
(this->*(forceCast<doubleClassAMemberfuncDouble_t>(f._function)))(4.321);
Unfortunately when it ran, it segfaulted. Further investigation shows that, at least on GCC for 32-bit Linux for x86, sizeof(a member function pointer) is 8, while sizeof(a nonmember function pointer) is 4. When I changed the type of FuncR::_function to uint64_t, amazingly, the call succeeded. (I was surprised as well.)
So it seems regardless of any casting magic you might find that compiles without error, there's really no way at all you'd ever be able to squeeze a member function pointer into a nonmember function pointer, at least on GCC for 32-bit x86. And even if you could, that doesn't encapsulate the 'this' pointer, as 'unwind' mentioned in his post.
I think there's still hope, though.
unwind's post suggests a trampoline function but concedes that it would require separately passing the 'this' pointer & managing that in the C code as a void*. I'm assuming your C library is not modifiable? If so, you should still be able to do a trampoline without being able to pass a 'this' pointer through it, assuming you have a limited number of such function pointers you'll need to be specifying:
You could create an array of class A object pointers, sized to however many of these FuncR function pointer objects you'll be using:
A* arrayThatHoldsAObjPointers[8]; // assuming you only need 8 such FuncR func ptr objects
Then create that many physical static nonmember functions (each conveniently named with a suffix number corresponding with its associated array index), and in the body of each, make them call A::foo() via its associated 'A' object in the arrayThatHoldsAObjPointers:
double trampoline_0(double d) { return arrayThatHoldsAObjPointers[0]->foo(d); }
double trampoline_1(double d) { return arrayThatHoldsAObjPointers[1]->foo(d); }
...and so on...
Then when you need to set a FuncR object for use by your C library, give it the address of one of the trampolines, and at the same time, store the pointer to that A object in the associated arrayThatHoldsAObjPointers[] element. To make the code that sets these easier to use, you could also create an array of function pointers to the trampolines.
Say you have:
struct c_struct {
int value;
/* other stuff */
void (* dump)();
};
and you'd like to, at some point:
c_struct_obj->dump();
I assume there's no way you could instantiate a c_struct object such that its particular "dump" function knows its particular "value" the way C++ methods know member variables (via the implicit "this" I suppose)? I guess I know the answer already ("no"). If so, are there other ways of using C structs in an OOPy way?
Sure, you just have to pass this by yourself:
struct c_struct {
int value;
/* other stuff */
void (* dump)(struct c_struct *this);
};
And then call it with:
c_struct_obj->dump(c_struct_obj);
You can use structs in this way but its a pain. All c++ member function get a *this pointer passed to them you can do the same but your dump functions will need to take the structure that its contained in as a parameter.
If you are using a C++ compiler, the only difference between a struct and a class is the default visibility of member variables (classes being private, structs being public). The this pointer is available within member functions.
struct test
{
int x;
void inc();
};
void test::inc()
{
x++;
}
int main(void)
{
test a;
a.x = 1;
a.inc();
int b = a.x;
return 0;
}
b == 2 here.
You can do this and can even do inheritance. But the interfacing with it is a total mess and you get nowhere near, for example, the resource safety involved with C++'s deterministic automatic cleanup. Ultimately, you CAN do OOP in C, but it's just not worth the hassle compared to just using C++, as well as all the other features that C++ offers.
Instead of having to remember to initialize a simple 'C' structure, I might derive from it and zero it in the constructor like this:
struct MY_STRUCT
{
int n1;
int n2;
};
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct()
{
memset(this, 0, sizeof(MY_STRUCT));
}
};
This trick is often used to initialize Win32 structures and can sometimes set the ubiquitous cbSize member.
Now, as long as there isn't a virtual function table for the memset call to destroy, is this a safe practice?
You can simply value-initialize the base, and all its members will be zero'ed out. This is guaranteed
struct MY_STRUCT
{
int n1;
int n2;
};
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct():MY_STRUCT() { }
};
For this to work, there should be no user declared constructor in the base class, like in your example.
No nasty memset for that. It's not guaranteed that memset works in your code, even though it should work in practice.
PREAMBLE:
While my answer is still Ok, I find litb's answer quite superior to mine because:
It teaches me a trick that I did not know (litb's answers usually have this effect, but this is the first time I write it down)
It answers exactly the question (that is, initializing the original struct's part to zero)
So please, consider litb's answer before mine. In fact, I suggest the question's author to consider litb's answer as the right one.
Original answer
Putting a true object (i.e. std::string) etc. inside will break, because the true object will be initialized before the memset, and then, overwritten by zeroes.
Using the initialization list doesn't work for g++ (I'm surprised...). Initialize it instead in the CMyStruct constructor body. It will be C++ friendly:
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct() { n1 = 0 ; n2 = 0 ; }
};
P.S.: I assumed you did have no control over MY_STRUCT, of course. With control, you would have added the constructor directly inside MY_STRUCT and forgotten about inheritance. Note that you can add non-virtual methods to a C-like struct, and still have it behave as a struct.
EDIT: Added missing parenthesis, after Lou Franco's comment. Thanks!
EDIT 2 : I tried the code on g++, and for some reason, using the initialization list does not work. I corrected the code using the body constructor. The solution is still valid, though.
Please reevaluate my post, as the original code was changed (see changelog for more info).
EDIT 3 : After reading Rob's comment, I guess he has a point worthy of discussion: "Agreed, but this could be an enormous Win32 structure which may change with a new SDK, so a memset is future proof."
I disagree: Knowing Microsoft, it won't change because of their need for perfect backward compatibility. They will create instead an extended MY_STRUCTEx struct with the same initial layout as MY_STRUCT, with additionnal members at the end, and recognizable through a "size" member variable like the struct used for a RegisterWindow, IIRC.
So the only valid point remaining from Rob's comment is the "enormous" struct. In this case, perhaps a memset is more convenient, but you will have to make MY_STRUCT a variable member of CMyStruct instead of inheriting from it.
I see another hack, but I guess this would break because of possible struct alignment problem.
EDIT 4: Please take a look at Frank Krueger's solution. I can't promise it's portable (I guess it is), but it is still interesting from a technical viewpoint because it shows one case where, in C++, the "this" pointer "address" moves from its base class to its inherited class.
Much better than a memset, you can use this little trick instead:
MY_STRUCT foo = { 0 };
This will initialize all members to 0 (or their default value iirc), no need to specifiy a value for each.
This would make me feel much safer as it should work even if there is a vtable (or the compiler will scream).
memset(static_cast<MY_STRUCT*>(this), 0, sizeof(MY_STRUCT));
I'm sure your solution will work, but I doubt there are any guarantees to be made when mixing memset and classes.
This is a perfect example of porting a C idiom to C++ (and why it might not always work...)
The problem you will have with using memset is that in C++, a struct and a class are exactly the same thing except that by default, a struct has public visibility and a class has private visibility.
Thus, what if later on, some well meaning programmer changes MY_STRUCT like so:
struct MY_STRUCT
{
int n1;
int n2;
// Provide a default implementation...
virtual int add() {return n1 + n2;}
};
By adding that single function, your memset might now cause havoc.
There is a detailed discussion in comp.lang.c+
The examples have "unspecified behaviour".
For a non-POD, the order by which the compiler lays out an object (all bases classes and members) is unspecified (ISO C++ 10/3). Consider the following:
struct A {
int i;
};
class B : public A { // 'B' is not a POD
public:
B ();
private:
int j;
};
This can be laid out as:
[ int i ][ int j ]
Or as:
[ int j ][ int i ]
Therefore, using memset directly on the address of 'this' is very much unspecified behaviour. One of the answers above, at first glance looks to be safer:
memset(static_cast<MY_STRUCT*>(this), 0, sizeof(MY_STRUCT));
I believe, however, that strictly speaking this too results in unspecified behaviour. I cannot find the normative text, however the note in 10/5 says: "A base class subobject may have a layout (3.7) different from the layout of a most derived object of the same type".
As a result, I compiler could perform space optimizations with the different members:
struct A {
char c1;
};
struct B {
char c2;
char c3;
char c4;
int i;
};
class C : public A, public B
{
public:
C ()
: c1 (10);
{
memset(static_cast<B*>(this), 0, sizeof(B));
}
};
Can be laid out as:
[ char c1 ] [ char c2, char c3, char c4, int i ]
On a 32 bit system, due to alighments etc. for 'B', sizeof(B) will most likely be 8 bytes. However, sizeof(C) can also be '8' bytes if the compiler packs the data members. Therefore the call to memset might overwrite the value given to 'c1'.
Precise layout of a class or structure is not guaranteed in C++, which is why you should not make assumptions about the size of it from the outside (that means if you're not a compiler).
Probably it works, until you find a compiler on which it doesn't, or you throw some vtable into the mix.
If you already have a constructor, why not just initialize it there with n1=0; n2=0; -- that's certainly the more normal way.
Edit: Actually, as paercebal has shown, ctor initialization is even better.
My opinion is no. I'm not sure what it gains either.
As your definition of CMyStruct changes and you add/delete members, this can lead to bugs. Easily.
Create a constructor for CMyStruct that takes a MyStruct has a parameter.
CMyStruct::CMyStruct(MyStruct &)
Or something of that sought. You can then initialize a public or private 'MyStruct' member.
From an ISO C++ viewpoint, there are two issues:
(1) Is the object a POD? The acronym stands for Plain Old Data, and the standard enumerates what you can't have in a POD (Wikipedia has a good summary). If it's not a POD, you can't memset it.
(2) Are there members for which all-bits-zero is invalid ? On Windows and Unix, the NULL pointer is all bits zero; it need not be. Floating point 0 has all bits zero in IEEE754, which is quite common, and on x86.
Frank Kruegers tip addresses your concerns by restricting the memset to the POD base of the non-POD class.
Try this - overload new.
EDIT: I should add - This is safe because the memory is zeroed before any constructors are called. Big flaw - only works if object is dynamically allocated.
struct MY_STRUCT
{
int n1;
int n2;
};
class CMyStruct : public MY_STRUCT
{
public:
CMyStruct()
{
// whatever
}
void* new(size_t size)
{
// dangerous
return memset(malloc(size),0,size);
// better
if (void *p = malloc(size))
{
return (memset(p, 0, size));
}
else
{
throw bad_alloc();
}
}
void delete(void *p, size_t size)
{
free(p);
}
};
If MY_STRUCT is your code, and you are happy using a C++ compiler, you can put the constructor there without wrapping in a class:
struct MY_STRUCT
{
int n1;
int n2;
MY_STRUCT(): n1(0), n2(0) {}
};
I'm not sure about efficiency, but I hate doing tricks when you haven't proved efficiency is needed.
Comment on litb's answer (seems I'm not yet allowed to comment directly):
Even with this nice C++-style solution you have to be very careful that you don't apply this naively to a struct containing a non-POD member.
Some compilers then don't initialize correctly anymore.
See this answer to a similar question.
I personally had the bad experience on VC2008 with an additional std::string.
What I do is use aggregate initialization, but only specifying initializers for members I care about, e.g:
STARTUPINFO si = {
sizeof si, /*cb*/
0, /*lpReserved*/
0, /*lpDesktop*/
"my window" /*lpTitle*/
};
The remaining members will be initialized to zeros of the appropriate type (as in Drealmer's post). Here, you are trusting Microsoft not to gratuitously break compatibility by adding new structure members in the middle (a reasonable assumption). This solution strikes me as optimal - one statement, no classes, no memset, no assumptions about the internal representation of floating point zero or null pointers.
I think the hacks involving inheritance are horrible style. Public inheritance means IS-A to most readers. Note also that you're inheriting from a class which isn't designed to be a base. As there's no virtual destructor, clients who delete a derived class instance through a pointer to base will invoke undefined behaviour.
I assume the structure is provided to you and cannot be modified. If you can change the structure, then the obvious solution is adding a constructor.
Don't over engineer your code with C++ wrappers when all you want is a simple macro to initialise your structure.
#include <stdio.h>
#define MY_STRUCT(x) MY_STRUCT x = {0}
struct MY_STRUCT
{
int n1;
int n2;
};
int main(int argc, char *argv[])
{
MY_STRUCT(s);
printf("n1(%d),n2(%d)\n", s.n1, s.n2);
return 0;
}
It's a bit of code, but it's reusable; include it once and it should work for any POD. You can pass an instance of this class to any function expecting a MY_STRUCT, or use the GetPointer function to pass it into a function that will modify the structure.
template <typename STR>
class CStructWrapper
{
private:
STR MyStruct;
public:
CStructWrapper() { STR temp = {}; MyStruct = temp;}
CStructWrapper(const STR &myStruct) : MyStruct(myStruct) {}
operator STR &() { return MyStruct; }
operator const STR &() const { return MyStruct; }
STR *GetPointer() { return &MyStruct; }
};
CStructWrapper<MY_STRUCT> myStruct;
CStructWrapper<ANOTHER_STRUCT> anotherStruct;
This way, you don't have to worry about whether NULLs are all 0, or floating point representations. As long as STR is a simple aggregate type, things will work. When STR is not a simple aggregate type, you'll get a compile-time error, so you won't have to worry about accidentally misusing this. Also, if the type contains something more complex, as long as it has a default constructor, you're ok:
struct MY_STRUCT2
{
int n1;
std::string s1;
};
CStructWrapper<MY_STRUCT2> myStruct2; // n1 is set to 0, s1 is set to "";
On the downside, it's slower since you're making an extra temporary copy, and the compiler will assign each member to 0 individually, instead of one memset.