Is this legal in c++11? Compiles with the latest intel compiler and appears to work, but I just get that feeling that it is a fluke.
class cbase
{
virtual void call();
};
template<typename T> class functor : public cbase
{
public:
functor(T* obj, void (T::*pfunc)())
: _obj(obj), _pfunc(pfunc) {}
virtual void call()
{
(_obj)(*_pfunc)();
}
private:
T& _obj;
void (T::*_pfunc)();
//edited: this is no good:
//const static int size = sizeof(_obj) + sizeof(_pfunc);
};
class signal
{
public:
template<typename T> void connect(T& obj, void (T::*pfunc)())
{
_ptr = new (space) functor<T>(obj, pfunc);
}
private:
cbase* _ptr;
class _generic_object {};
typename aligned_storage<sizeof(functor<_generic_object>),
alignment_of<functor<_generic_object>>::value>::type space;
//edited: this is no good:
//void* space[(c1<_generic_object>::size / sizeof(void*))];
};
Specifically I'm wondering if void* space[(c1<_generic_object>::size / sizeof(void*))]; is really going to give the correct size for c1's member objects (_obj and _pfunc). (It isn't).
EDIT:
So after some more research it would seem that the following would be (more?) correct:
typename aligned_storage<sizeof(c1<_generic_object>),
alignment_of<c1<_generic_object>>::value>::type space;
However upon inspecting the generated assembly, using placement new with this space seems to inhibit the compiler from optimizing away the call to 'new' (which seemed to happen while using just regular '_ptr = new c1;'
EDIT2: Changed the code to make intentions a little clearer.
const static int size = sizeof(_obj) + sizeof(_pfunc); will give the sum of the sizes of the members, but that may not be the same as the size of the class containing those members. The compiler is free to insert padding between members or after the last member. As such, adding together the sizes of the members approximates the smallest that object could possibly be, but doesn't necessarily give the size of an object with those members.
In fact, the size of an object can vary depending not only on the types of its members, but also on their order. For example:
struct A {
int a;
char b;
};
vs:
struct B {
char b;
int a;
};
In many cases, A will be smaller than B. In A, there will typically be no padding between a and b, but in B, there will often be some padding (e.g., with a 4-byte int, there will often be 3 bytes of padding between b and a).
As such, your space may not contain enough...space to hold the object you're trying to create there in init.
I think you just got lucky; Jerry's answer points out that there may be padding issues. What I think you have is a non-virtual class (i.e., no vtable), with essentially two pointers (under the hood).
That aside, the arithmetic: (c1<_generic_object>::size / sizeof(void*)) is flawed because it will truncate if size is not a multiple of sizeof(void *). You would need something like:
((c1<_generic_object>::size + sizeof(void *) - 1) / sizeof(void *))
This code does not even get to padding issues, because it has a few of more immediate ones.
Template class c1 is defined to contain a member T &_obj of reference type. Applying sizeof to _obj in scope of c1 will evaluate to the size of T, not to the size of reference member itself. It is not possible to obtain the physical size of a reference in C++ (at least directly). Meanwhile, any actual object of type c1<T> will physically contain a reference to T, which is typically implemented in such cases as a pointer "under the hood".
For this reason it is completely unclear to me why the value of c1<_generic_object>::size is used as a measure of memory required for in-pace construction of an actual object of type c1<T> (for any T). It just doesn't make any sense. These sizes are not related at all.
By pure luck the size of an empty class _generic_object might evaluate to the same (or greater) value as the size of a physical implementation of a reference member. In that case the code will allocate a sufficient amount of memory. One might even claim that the sizeof(_generic_object) == sizeof(void *) equality will "usually" hold in practice. But that would be just a completely arbitrary coincidence with no meaningful basis whatsoever.
This even looks like red herring deliberately inserted into the code for the purpose of pure obfuscation.
P.S. In GCC sizeof of an empty class actually evaluates to 1, not to any "aligned" size. Which means that the above technique is guaranteed to initialize c1<_generic_object>::size with a value that is too small. More specifically, in 32 bit GCC the value of c1<_generic_object>::size will be 9, while the actual size of any c1<some_type_t> will be 12 bytes.
Related
I have tried union...
struct foo
{
union
{
struct // 2 bytes
{
char var0_1;
};
struct // 5 bytes
{
char var1_1;
int var1_2;
};
};
};
Problem: Unions do what I want, except they will always take the size of the biggest datatype. In my case I need struct foo to have some initialization that allows me to tell it which structure to chose of the two (if that is even legal) as shown below.
So after that, I tried class template overloading...
template <bool B>
class foo { }
template <>
class foo<true>
{
char var1;
}
template <>
class foo<false>
{
char var0;
int var1;
}
Problem: I was really happy with templates and the fact that I could use the same variable name on the char and int, but the problem was the syntax. Because the classes are created on compile-time, the template boolean variable needed to be a hardcoded constant, but in my case the boolean needs to be user-defined on runtime.
So I need something of the two "worlds." How can I achieve what I'm trying to do?
!!NOTE: The foo class/struct will later be inherited, therefore as already mentioned, size of foo is of utmost importance.
EDIT#1::
Application:
Basically this will be used to read/write (using a pointer as an interface) a specific data buffer and also allow me to create (new instance of the class/struct) the same data buffer. The variables you see above specify the length. If it's a smaller data buffer, the length is written in a char/byte. If it's a bigger data buffer, the first char/byte is null as a flag, and the int specifies the length instead. After the length it's obvious that the actual data follows, hence why the inheritance. Size of class is of the utmost importance. I need to have my cake and eat it too.
A layer of abstraction.
struct my_buffer_view{
std::size_t size()const{
if (!m_ptr)return 0;
if (*m_ptr)return *m_ptr;
return *reinterpret_cast<std::uint32_t const*>(m_ptr+1);
}
std::uint8_t const* data() const{
if(!m_ptr)return nullptr;
if(*m_ptr)return m_ptr+1;
return m_ptr+5;
}
std::uint8_t const* begin()const{return data();}
std::uint8_t const* end()const{return data()+size();}
my_buffer_view(std::uint_t const*ptr=nullptr):m_ptr(ptr){}
my_buffer_view(my_buffer_view const&)=default;
my_buffer_view& operator=(my_buffer_view const&)=default;
private:
std::uint8_t const* m_ptr=0;
};
No variable sized data anywhere. I coukd have used a union for size etx:
struct header{
std::uint8_t short_len;
union {
struct{
std::uint32_t long_len;
std::uint8_t long_buf[1];
}
struct {
std::short_buf[1];
}
} body;
};
but I just did pointer arithmetic instead.
Writing such a buffer to a bytestream is another problem entirely.
Your solution does not make sense. Think about your solution: you could define two independents classes: fooTrue and fooFalse with corresponding members exactly with the same result.
Probably, you are looking for a different solution as inheritance. For example, your fooTrue is baseFoo and your fooFalse is derivedFoo with as the previous one as base and extends it with another int member.
In this case, you have the polymorphism as the method to work in runtime.
You can't have your cake and eat it too.
The point of templates is that the specialisation happens at compile time. At run time, the size of the class is fixed (albeit, in an implementation-defined manner).
If you want the choice to be made at run time, then you can't use a mechanism that determines size at compile-time. You will need a mechanism that accommodates both possible needs. Practically, that means your base class will need to be large enough to contain all required members - which is essentially what is happening with your union based solution.
In reference to your "!!NOTE". What you are doing qualifies as premature optimisation. You are trying to optimise size of a base class without any evidence (e.g. measurement of memory usage) that the size difference is actually significant for your application (e.g. that it causes your application to exhaust available memory). The fact that something will be a base for a number of other classes is not sufficient, on its own, to worry about its size.
I am implementing my C#-like property class in C++.
So I have to provide acceess to the internal field(mother::_i) to the property field(mother::i).
I found few solutions but there were no perfects.
Firstly I made a method to provide owner(mother in this case)'s pointer on runtime by calling method like RProperty<...>::SetOwner(mother&). But it requires additional code to use my property class and costs in runtime.
Secondly I came up with idea that this pointer of RProperty and member pointer of itself can find the owner's pointer. obviously, ownerpointer = this - &mother::i. But providing member pointer to member itself gives me compile time error. I tried a tricky method using 'empty' struct to provide member pointer to property. But it turns out sizeof(struct empty) is not zero. it costs unnecessary extra memory per instances. I stucked in this issue for few days.
anyone has a good idea? :)
Code works but not perfect:
#include "stdafx.h"
struct empty{};
template<typename TCLASS, typename TFIELD>
class RPropertyBase
{
protected:
RPropertyBase(){ }
TCLASS& getOwner() const { };
};
template<typename TCLASS, typename TFIELD, TFIELD TCLASS::*PFIELD, empty TCLASS::*PTHIS>
class RProperty : RPropertyBase<TCLASS, TFIELD>
{
protected:
TCLASS& getOwner() const { return *(TCLASS*)((unsigned int)this-(unsigned int)&(((TCLASS*)0)->*PTHIS)-sizeof(empty) ); }
public:
RProperty<TCLASS, TFIELD, PFIELD, PTHIS>& operator=(const TFIELD& A){ getOwner().*PFIELD = A; return *this; }
operator TFIELD&() const { return getOwner().*PFIELD; }
};
class mother
{
int _i;
template<typename C>
struct __Propertyi : public RProperty<C, int, &C::_i, &C::_empty>
{
using RProperty<C, int, &C::_i, &C::_empty>::operator=;
};
public:
empty _empty;
__Propertyi<mother> i;
};
int _tmain(int argc, _TCHAR* argv[])
{
mother a;
a.i = 1;
int bb = (a.i);
return 0;
}
First...
So I have to provide acceess to the internal field(mother::_i) to the property field(mother::i).
Identifiers beginning with an underscore are reserved in C++ - only the compiler and it's libraries are supposed to use them. Identifiers containing double-underscores are also reserved. However, identifiers with a single trailing underscore such as i_ are OK.
Getting to the point...
ownerpointer = this - &mother::i
It looks like you're trying to subtract a member pointer from a pointer, which you can't do. Member pointers are a bit like offsets into the layout of a type, but this breaks down in two ways...
It's not the abstraction they're designed to provide.
It's not accurate anyway - once you allow for multiple inheritance and virtual inheritance, the offset at which a particular member appears within a type doesn't just depend on it's position within the base type in which it's defined, but also on which subtype you're looking at.
If you really want to do pointer arithmetic that's aware of the layout of a type, it's certainly possible, but it's a C programming technique that uses C-level features. There's also some significant limitations on context.
The key idea is that instead of trying to use member pointers as offsets, you use actual offsets. This costs you type-safety but, so long as you wrap the type-unsafe code and make absolutely certain it's correct, you should be OK.
The basic tool is offsetof, which is a macro that C++ inherits from C...
offsetof(structname, membername)
You can look up the implementation of that macro, but don't copy it - the standard requires that a compiler provide some way to implement the macro that works, but the implementation that works for one compiler may not work for another. However, two common approaches are...
Look at the address of the member in an imaginary instance of the struct at address zero. Problems with this (e.g. that imaginary instance obviously doesn't have a valid virtual pointer) are part of the reason for some restrictions.
Use a special "intrinsic" function provided by the compiler, which is one of the reasons why those identifiers with underscores are reserved.
Using that offset, in principle, you can cast your pointer to char* via void*, do your arithmetic, then cast back again to the needed type.
The first problem is obvious - some members (ie the static ones) aren't at a fixed offset in each instance, they're at a fixed address irrespective of the instance. Obvious but perhaps best to say it.
The next problem is from that offsetof documentation I linked...
type shall be a POD class (including unions).
You're looking at the layout of a type. You need that layout to apply to subtypes as well. Because you've discarded the C++ polymorphism abstraction and you're dealing directly with offsets, the compiler can't handle any run-time layout resolution for you. Various inheritance-related issues would invalidate the offset calculations - multiple inheritance, virtual inheritance, a subtype that has a virtual pointer when the base doesn't.
So you need to do your layout with a POD struct. You can get away with single inheritance, but you can't have virtual methods. But there's another annoyance - POD is a bit of an overloaded term that obviously doesn't just relate to whether offsetof is valid or not. A type that has non-POD data members isn't POD.
I hit this problem with a multiway tree data structure. I used offsetof to implement the data structure (because different times). I wrapped this in a template, which used a struct and offsetof to determine the node layouts. In a whole series of compilers and compiler versions this was fine until I switched to a version of GCC, which started warning all over the place.
My question and answer about this on SO are here.
This issue with offsetof may have been addressed in C++11 - I'm not sure. In any case, even though a member within a struct is non-POD, that struct will still have a fixed layout determined at compile time. The offset is OK even if the compiler throws warnings at you, which luckily in GCC can be turned off.
The next problem from that offsetof documentation I linked...
type shall be a standard-layout class (including unions).
This is a new one from C++11 and, to be honest, I haven't really thought about it much myself.
The final problem - actually, the view of a pointer as an address is invalid. Sure, the compiler implements pointers as addresses, but there's lots of technicalities, and compiler writers have been exploiting these in their optimisers.
One area you have to be very careful with once you start doing pointer arithmetic is the compilers "alias analysis" - how it decides whether two pointers might point to the same thing (in order to decide when it can safely keep values in registers and not refer back to memory to see if a write through an alias pointer changed it). I once asked this question about that, but it turns out the answer I accepted is a problem (I should probably go back and do something about it) because although it describes the problem correctly, the solution it suggests (using union-based puns) is only correct for GCC and not guaranteed by the C++ standard.
In the end, my solution was to hide the pointer arithmetic (and char* pointers) in a set of functions...
inline void* Ptr_Add (void* p1, std::ptrdiff_t p2)
{
return (((char*) p1) + p2);
}
inline void* Ptr_Sub (void* p1, std::ptrdiff_t p2)
{
return (((char*) p1) - p2);
}
inline std::ptrdiff_t Ptr_Diff (void* p1, void* p2)
{
return (((char*) p1) - ((char*) p2));
}
inline bool Ptr_EQ (void* p1, void* p2) { return (((char*) p1) == ((char*) p2)); }
inline bool Ptr_NE (void* p1, void* p2) { return (((char*) p1) != ((char*) p2)); }
inline bool Ptr_GT (void* p1, void* p2) { return (((char*) p1) > ((char*) p2)); }
inline bool Ptr_GE (void* p1, void* p2) { return (((char*) p1) >= ((char*) p2)); }
inline bool Ptr_LT (void* p1, void* p2) { return (((char*) p1) < ((char*) p2)); }
inline bool Ptr_LE (void* p1, void* p2) { return (((char*) p1) <= ((char*) p2)); }
That std::ptrdiff_t type is significant too - the bit-width of a pointer isn't guaranteed to match the bit-width of a long.
Outside of these functions, all pointers are either their correct type or void*. C++ treats void* specially (the compiler knows it can alias other pointer types) so it seems to work, though there may be details I'm not remembering. Sorry - these things are hard, especially these days with optimisers that are sometimes clever in the "obnoxious pedant" sense, and I only touch this evil code if I absolutely have to.
One last issue - I already mentioned that pointers aren't addresses. One oddity is that on some platforms, two different pointers may map to the same address in different address spaces - see for example the Harvard Architecture which has different address spaces for instructions. So even the offset between two pointers is invalid except within certain limits, no doubt described in complicated detail in the standard. A single struct is a single struct - obviously it lives on one address space, with the possible exception of static members - but don't just assume pointer arithmetic is always valid.
Long story short - yes, it's possible to subtract the offset of a member from the address of a member to find the address of the struct, but you have to use actual offsets (not member pointers) and there are limitations and technicalities that may mean you can't even solve your problem this way (e.g. I'm not sure you'll be able to use offsets as template parameters), and certainly mean it's harder than it seems.
Ultimately, the take-away advice is that if you read this, treat it as a warning. Don't do the things I've done. I wish I hadn't, and probably so will you.
This question is not about the C++ language itself(ie not about the Standard) but about how to call a compiler to implement alternative schemes for virtual function.
The general scheme for implementing virtual functions is using a pointer to a table of pointers.
class Base {
private:
int m;
public:
virtual metha();
};
equivalently in say C would be something like
struct Base {
void (**vtable)();
int m;
}
the first member is usually a pointer to a list of virtual functions, etc. (a piece of area in the memory which the application has no control of). And in most case this happens to cost the size of a pointer before considering the members, etc. So in a 32bit addressing scheme around 4 bytes, etc. If you created a list of 40k polymorphic objects in your applications, this is around 40k x 4 bytes = 160k bytes before any member variables, etc. I also know this happens to be the fastest and common implementation among C++ compiles.
I know this is complicated by multiple inheritance (especially with virtual classes in them, ie diamond struct, etc).
An alternative way to do the same is to have the first variable as a index id to a table of vptrs(equivalently in C as below)
struct Base {
char classid; // the classid here is an index into an array of vtables
int m;
}
If the total number of classes in an application is less than 255(including all possible template instantiations, etc), then a char is good enough to hold an index thereby reducing the size of all polymorphic classes in the application(I am excluding alignment issues, etc).
My questions is, is there any switch in GNU C++, LLVM, or any other compiler to do this?? or reduce the size of polymorphic objects?
Edit: I understand about the alignment issues pointed out. Also a further point, if this was on a 64bit system(assuming 64bit vptr) with each polymorphic object members costing around 8 bytes, then the cost of vptr is 50% of the memory. This mostly relates to small polymorphics created in mass, so I am wondering if this scheme is possible for at least specific virtual objects if not the whole application.
You're suggestion is interesting, but it won't work if the executable is made of several modules, passing objects among them. Given they are compiled separately (say DLLs), if one module creates an object and passes it to another, and the other invokes a virtual method - how would it know which table the classid refers to? You won't be able to add another moduleid because the two modules might not know about each other when they are compiled. So unless you use pointers, I think it's a dead end...
A couple of observations:
Yes, a smaller value could be used to represent the class, but some processors require data to be aligned so that saving in space may be lost by the requirement to align data values to e.g. 4 byte boundaries. Further, the class-id must be in a well defined place for all members of a polymorphic inheritance tree, so it is likely to be ahead of other date, so alignment problems can't be avoided.
The cost of storing the pointer has been moved to the code, where every use of a polymorphic function requires code to translate the class-id to either a vtable pointer, or some equivalent data structure. So it isn't for free. Clearly the cost trade-off depends on the volume of code vs numer of objects.
If objects are allocated from the heap, there is usually space wasted in orer to ensure objects are alogned to the worst boundary, so even if there is a small amount of code, and a large number of polymorphic objects, the memory management overhead migh be significantly bigger than the difference between a pointer and a char.
In order to allow programs to be independently compiled, the number of classes in the whole program, and hence the size of the class-id must be known at compile time, otherwise code can't be compiled to access it. This would be a significant overhead. It is simpler to fix it for the worst case, and simplify compilation and linking.
Please don't let me stop you trying, but there are quite a lot more issues to resolve using any technique which may use a variable size id to derive the function address.
I would strongly encourage you to look at Ian Piumarta's Cola also at Wikipedia Cola
It actually takes a different approach, and uses the pointer in a much more flexible way, to to build inheritance, or prototype-based, or any other mechanism the developer requires.
No, there is no such switch.
The LLVM/Clang codebase avoids virtual tables in classes that are allocated by the tens of thousands: this work well in a closed hierachy, because a single enum can enumerate all possible classes and then each class is linked to a value of the enum. The closed is obviously because of the enum.
Then, virtuality is implemented by a switch on the enum, and appropriate casting before calling the method. Once again, closed. The switch has to be modified for each new class.
A first alternative: external vpointer.
If you find yourself in a situation where the vpointer tax is paid way too often, that is most of the objects are of known type. Then you can externalize it.
class Interface {
public:
virtual ~Interface() {}
virtual Interface* clone() const = 0; // might be worth it
virtual void updateCount(int) = 0;
protected:
Interface(Interface const&) {}
Interface& operator=(Interface const&) { return *this; }
};
template <typename T>
class InterfaceBridge: public Interface {
public:
InterfaceBridge(T& t): t(t) {}
virtual InterfaceBridge* clone() const { return new InterfaceBridge(*this); }
virtual void updateCount(int i) { t.updateCount(i); }
private:
T& t; // value or reference ? Choose...
};
template <typename T>
InterfaceBridge<T> interface(T& t) { return InterfaceBridge<T>(t); }
Then, imagining a simple class:
class Counter {
public:
int getCount() const { return c; }
void updateCount(int i) { c = i; }
private:
int c;
};
You can store the objects in an array:
static Counter array[5];
assert(sizeof(array) == sizeof(int)*5); // no v-pointer
And still use them with polymorphic functions:
void five(Interface& i) { i.updateCount(5); }
InterfaceBridge<Counter> ib(array[3]); // create *one* v-pointer
five(ib);
assert(array[3].getCount() == 5);
The value vs reference is actually a design tension. In general, if you need to clone you need to store by value, and you need to clone when you store by base class (boost::ptr_vector for example). It is possible to actually provide both interfaces (and bridges):
Interface <--- ClonableInterface
| |
InterfaceB ClonableInterfaceB
It's just extra typing.
Another solution, much more involved.
A switch is implementable by a jump table. Such a table could perfectly be created at runtime, in a std::vector for example:
class Base {
public:
~Base() { VTables()[vpointer].dispose(*this); }
void updateCount(int i) {
VTables()[vpointer].updateCount(*this, i);
}
protected:
struct VTable {
typedef void (*Dispose)(Base&);
typedef void (*UpdateCount)(Base&, int);
Dispose dispose;
UpdateCount updateCount;
};
static void NoDispose(Base&) {}
static unsigned RegisterTable(VTable t) {
std::vector<VTable>& v = VTables();
v.push_back(t);
return v.size() - 1;
}
explicit Base(unsigned id): vpointer(id) {
assert(id < VTables.size());
}
private:
// Implement in .cpp or pay the cost of weak symbols.
static std::vector<VTable> VTables() { static std::vector<VTable> VT; return VT; }
unsigned vpointer;
};
And then, a Derived class:
class Derived: public Base {
public:
Derived(): Base(GetID()) {}
private:
static void UpdateCount(Base& b, int i) {
static_cast<Derived&>(b).count = i;
}
static unsigned GetID() {
static unsigned ID = RegisterTable(VTable({&NoDispose, &UpdateCount}));
return ID;
}
unsigned count;
};
Well, now you'll realize how great it is that the compiler does it for you, even at the cost of some overhead.
Oh, and because of alignment, as soon as a Derived class introduces a pointer, there is a risk that 4 bytes of padding are used between Base and the next attribute. You can use them by careful selecting the first few attributes in Derived to avoid padding...
The short answer is that no, I don't know of any switch to do this with any common C++ compiler.
The longer answer is that to do this, you'd just about have to build most of the intelligence into the linker, so it could coordinate distributing the IDs across all the object files getting linked together.
I'd also point out that it wouldn't generally do a whole lot of good. At least in a typical case, you want each element in a struct/class at a "natural" boundary, meaning its starting address is a multiple of its size. Using your example of a class containing a single int, the compiler would allocate one byte for the vtable index, followed immediately by three byes of padding so the next int would land at an address that was a multiple of four. The end result would be that objects of the class would occupy precisely the same amount of storage as if we used a pointer.
I'd add that this is not a far-fetched exception either. For years, standard advice to minimize padding inserted into structs/classes has been to put the items expected to be largest at the beginning, and progress toward the smallest. That means in most code, you'd end up with those same three bytes of padding before the first explicitly defined member of the struct.
To get any good from this, you'd have to be aware of it, and have a struct with (for example) three bytes of data you could move where you wanted. Then you'd move those to be the first items explicitly defined in the struct. Unfortunately, that would also mean that if you turned this switch off so you have a vtable pointer, you'd end up with the compiler inserting padding that might otherwise be unnecessary.
To summarize: it's not implemented, and if it was wouldn't usually accomplish much.
I have some code that implements a kind of run-time reflection. In order to get a pointer to a field of a class inside a given instance, i basically take the pointer to the class instance and add a fixed offset that is calculated once for each field that is exposed to the reflection library.
I kept the implementation quite simple, since i didn't need to support multiple inheritance and i made the mistake of not taking into account that, even with single inheritance, this situation is possible:
class A
{
public:
unsigned int m_uiField;
};
class B : public A
{
virtual void VirtualMethod()
{
}
};
int main()
{
unsigned int uiOffsetA(reinterpret_cast<unsigned int>(&(reinterpret_cast<A *>(0)->m_uiField)));
// uiOffsetA is 0 on VC9
unsigned int uiOffsetB(reinterpret_cast<unsigned int>(&(reinterpret_cast<B *>(0)->m_uiField)));
// uiOffsetB is 4 on VC9
}
In this case the virtual table pointer that my compiler puts at the beginning of each instance of B was offsetting by 4 bytes the fields of A.
My first idea was to do something similar to what i'm doing for the field offsets and store a single unsigned int as an offset for the base class to add to pointers to derived class instances together with the field offset. So, at initialization time i call this function one for each Derived class inheriting from a Base class:
template <typename Base, typename Derived>
unsigned int GetBaseClassOffset()
{
Derived *pDerived(reinterpret_cast<Derived *>(4));
Base *pBase(pDerived);
assert(pBase >= pDerived);
return reinterpret_cast<unsigned int>(pBase) - reinterpret_cast<unsigned int>(pDerived);
}
And everything seems to work with my tests using VC9.
But then it came to my mind that this area of C++ could be implementation dependent, and that other things like alignment could break this up.
In the end my question is:
Can i assume that fields of a base class will always be positioned at a constant positive offset relative to a pointer to a derived class instance?
Note: i am not saying "constant across all compilers", i will use some code (eventually compiler dependent) to detect this offset at startup.
For this situation, you can use pointer-to-members:
See it live: http://ideone.com/U4w7j
struct A
{
unsigned int m_uiField;
};
struct B : A
{
virtual void VirtualMethod() { }
};
int main()
{
A instance_a;
B instance_b;
unsigned int A::* ptrA = &A::m_uiField;
unsigned int B::* ptrB = &B::m_uiField;
// application:
unsigned int value = instance_a.*ptrA;
value = instance_b.*ptrA;
//value = instance_a.*ptrB; // incompatible types
value = instance_b.*ptrB;
// also:
A* dynamic = new B();
value = dynamic->*ptrA; // etc
}
I suggest you also look at template metaprogramming features (part of TR1 and C++11 now:), notably the is_pod type trait:
http://publib.boulder.ibm.com/infocenter/comphelp/v9v111/index.jsp?topic=/com.ibm.xlcpp9.aix.doc/standlib/header_type_traits.htm
http://www.boost.org/doc/libs/1_47_0/libs/type_traits/doc/html/boost_typetraits/reference/is_pod.html
http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.1/structstd_1_1tr1_1_1is__pod.html
http://msdn.microsoft.com/en-us/library/bb982918(v=VS.100).aspx
This is important because using offsetof on anything else is hazardous.
Standard-conformant implementation of reflection in C++ (including C++11) is not possible. Mainly because member offset is not standardized and so depends of compiler. It depends on polimorphism implementation, on alignment and probably on other things.
You can implement reflection for specific compiler, or for limited range of classes.
Much more info about C++ reflection is here.
Reflection support was proposed for C++11 standard but was postponed because required much more time.
Can i assume that fields of a base class will always be positioned at a constant positive offset relative to a pointer to a derived class instance?
No, you can't. Why is that a possitive offset? I would expect that in common implementations base members are placed before the derived classes?
Note the standard 'operator' (well not quite) offsetof, which will give you the offset from a struct to a member. It's usually implemented as a macro similar to yours, derreferencing the null pointer. It probably won't help you since its guaranteed to work only with POD type classes. See 18.2/4 at the standard:
The macro offsetof(type, member-designator) accepts a restricted set of type arguments in this International
Standard. If type is not a standard-layout class (Clause 9), the results are undeļ¬ned.
What would be a decent approach to check at compile/run-time that a particular struct/class does not have any virtual functions. This check is required in order to ensure the proper byte alignment when doing placement new.
Having so much as a single virtual function will shift the entire data by a vtable pointer size, which will completely mess things up in conjunction with the placement new operator.
Some more details: I need something that works across all major compiler and platforms, e.g. VS2005, VC++10, GCC 4.5, and Sun Studio 12.1 on top of Windows, Linux, and Solaris.
Something that is guaranteed to work with the following scenario should suffice:
struct A { char c; void m(); };
struct B : A { void m(); };
Should someone decide to make this change:
struct A { char c; virtual void m(); };
struct B : A { void m(); };
It would be great to see a compile-time error that says struct A must not contain virtual functions.
There are facilities and tricks (depending on the version of C++ you are using) to get the proper alignment for a class.
In C++0x, the alignof command is similar to sizeof but returns the required alignment instead.
In C++03, the first thing to note is that the size is a multiple of the alignment, because elements need be contiguous in an array. This means that using the size as the alignment is over-zealous (and may waste space) but works fine. With some trickery you can get a better value:
template <typename T>
struct AlignHelper
{
T t;
char c;
};
template <typename T>
struct Alignment
{
static size_t const diff = sizeof(AlignHelper<T>) - sizeof(T);
static size_t const value = (diff != 0) ? diff : sizeof(T);
};
This little helper gives a correct alignment as a compile-time constant (suitable for template programming therefore). It may be larger than the minimal alignment required (*).
Normally though it should be fine to use placement new, unless you are actually using it on a "raw buffer". In this case, the size of the buffer should be determined with the following formula:
// C++03
char buffer[sizeof(T) + alignof(T) - 1];
Or you should make use of C++0x facilities:
// C++0x
std::aligned_storage<sizeof(T), alignof(T)> buffer;
Another trick to ensure a "right" alignment for virtual tables it to make use of the union:
// C++03 and C++0x
union { char raw[sizeof(T)]; void* aligner; } buffer;
The aligner parameter guarantees that the buffer is correctly aligned for pointers, and thus for virtual tables pointers as well.
EDIT: Additional explanations as suggested by #Tony.
(*) How does this work ?
To understand it we need to delve into the memory representation of a class. Each subelement of a class has its own alignment requirement, so for example:
struct A { int a; char b; int c; };
+----+-+---+----+
| a |b|xxx| c |
+----+-+---+----+
Where xxx denotes padding added so that c is suitably aligned.
What is the alignment of A ? Generally speaking, it is the stricter alignment of the subelements, so here, the alignment of int (which is often 4 since int is often a 32 bits integral).
To "guess" the alignment of an arbitrary type, we thus "trick" the compiler by using the AlignHelper template. Remember that sizeof(AlignHelper<T>) must be a multiple of the alignment because types should be laid out contiguously in an array, thus we hope our type will be padded after the c attribute, and the alignment will be the size of c (1 by definition) plus the size of the padding.
// AlignHelper<T>
+----------------+-+---+
| t |c|xxx|
+----------------+-+---+
// T
+----------------+
| t |
+----------------+
When we do sizeof(AlignHelper<T>) - sizeof(T) we get this difference. Surprisingly though, it could be 0.
The issue comes from the fact that if there is some padding (unused bytes) at the end of T, then a smart compiler could decide to stash c there, and thus the difference of size would be 0.
We could, obviously, try to recursively increase the size of c attribute (using a char array), until we finally get a non-zero difference. In which case we would get a "tight" alignment, but the simplest thing to do is to bail out and use sizeof(T), since we already know it is a multiple of the alignment.
Finally, there is no guarantee that the alignment we get with this method is the alignment of T, we get a multiple of it, but it could be bigger, since sizeof is implementation dependent and a compiler could decide to align all types on power of 2 boundaries, for example.
What would be a decent approach to
check at compile/run-time that a
particular struct/class does not have
any virtual functions
template<typename T>
struct Is_Polymorphic
{
struct Test : T { virtual ~Test() = 0; };
static const bool value = (sizeof(T) == sizeof(Test));
};
Above class can help you to check if the given class is polymorphic or not at compile time. [Note: virtual inheritance also have a vtable included]
You are almost certainly doing something wrong.
However, given that you have decided to do something wrong, you don't want to know if your tpe has no virtual functions. You want to know if it is okay to treat your type as an array of bytes.
In C++03, is your type POD? As luck would have it, there's a trait for that, aptly named is_pod<T>. This is provided by Boost/TR1 in C++03, although it requires a relatively modern compiler [gcc > 4.3, MSVC > 8, others I don't know].
In C++11, you can ease up your requirements by asking if your type is trivially copiable. Again, there's a trait for that: is_trivially_copyable<T>.
In either case, there is also is_polymorphic<T>, but as I said, that's really not what you want anyhow. If you are using an older compiler, it does have the advantage of working out of the box if you get it from Boost; it performs the sizeof test mentioned elsewhere, rather than simply reporting false for all user defined types as is the case with is_pod.
No matter what, you'd better be 120% sure your constructor is a noop; that's not something that can be verified.
I just saw your edit. Of what you listed, Sun Studio is the only one that might not have the necessary intrinsics for these traits to work. gcc and MSVC have both had them for several years now.
dynamic_cast is only allowed for polymorphic classes, so you can utilize that for a compile time check.
Use is_pod type trait from tr1?
There is no feature for you to determine whether a class has virtual functions are not.