are member pointers fixed in size and reinterpret_cast? - c++

I am trying to create a template class that contains a pointer to an arbitrary class instance and function as follows:
template<class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
FunctPtr functPtr_;
C* instPtr_;
public:
A(FunctPtr functPtr, C* instPtr)
: functPtr_(functPtr)
, instPtr_(instPtr) {}
};
However, I want to be able to create instances of this class without dynamic memory allocation using placement new. Does the C++ standard guarantee this template class is of fixed size for all classes C?
In Don Clugston's article on pointers I noticed a chart of the various sizes for member functions pointers on various compilers and a few compilers aren't always the same size. I thought I was hosed but is this standards compliant? From the C++ standard sec. 5.2.10 on Reinterpret cast:
— converting a prvalue of type “pointer to member function” to a different pointer to member function
type and back to its original type yields the original pointer to member value.
Would that statement from the C++ standard indicate member function pointers are all of the same size?
If not I suppose I could still rewrite the code as follows to take advantage of that reinterpret_cast guarantee explicitly:
class GenericClass;
template<class C>
class A {
typedef void (GenericClass::*GenFunctPtr)();
typedef void (C::*SpecificFunctPtr)();
GenFunctPtr functPtr_; //store any kind of function ptr in this fixed format
GenericClass* instPtr_;
public:
A(SpecificFunctPtr functPtr, C* instPtr)
: functPtr_(reinterpret_cast<GenFunctPtr>(functPtr))
, instPtr_(reinterpret_cast<GenericClass*>(instPtr)) {}
void DoSomething()
{
//now convert pointers back to the original type to use...
reinterpret_cast<SpecificFunctPtr>(functPtr_);
reinterpret_cast<C*>(instPtr_);
}
};
This now would seem to be required to be all the same size and yet be standards compliant, right? I'd prefer the first option however if I must the 2nd will also work. Thoughts?

I don't know if the implementation details of pointer-to-member are specified in the standard (can't find it), but since we know that C* will have the same size for all C, we can just determine the size of FunctPtr for various types C and just add a static_assert:
template <class C>
class A {
typedef void (C::*FunctPtr)(); //e.g. void C::some_funct();
static_assert(sizeof(FunctPtr) == 16,
"unexpected FunctPtr size"); // from coliru, clang and gcc
FunctPtr functPtr_;
C* instPtr_;
...
};
At least I tried this with several types of classes ({base, derived, multiple derived} x {virtual, non-virtual}) and it always gave the same size.
This is probably platform and/or compiler specific, as Pointers to member functions are very strange animals indicates:
The size of a pointer-to-member-function of a class that uses only single inheritance is just the size of a pointer.
The size of a pointer-to-member-function of a class that uses multiple inheritance is the size of a pointer plus the size of a size_t.
which is not what I see in clang or gcc.

Microsoft compilers use different sizes of member pointers depending on how complex the class is. Technically this isn't compliant (since you can define pointers to members even when the class definition isn't visible), but it works sufficiently well in practice that they do it by default. Pragmas and compiler switches are available to control this behaviour. See for example https://msdn.microsoft.com/en-us/library/83cch5a6.aspx.
Even so the pointers for any given class are always the same size, it's just different classes may have different sized pointers to members.

Related

Base class fields offset

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 undefined.

How do boost::variant and boost::any work?

How do variant and any from the boost library work internally? In a project I am working on, I currently use a tagged union. I want to use something else, because unions in C++ don't let you use objects with constructors, destructors or overloaded assignment operators.
I queried the size of any and variant, and did some experiments with them. In my platform, variant takes the size of its longest possible type plus 8 bytes: I think it my just be 8 bytes o type information and the rest being the stored value. On the other hand, any just takes 8 bytes. Since i'm on a 64-bit platform, I guess any just holds a pointer.
How does Any know what type it holds? How does Variant achieve what it does through templates? I would like to know more about these classes before using them.
If you read the boost::any documentation they provide the source for the idea: http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf
It's basic information hiding, an essential C++ skill to have. Learn it!
Since the highest voted answer here is totally incorrect, and I have my doubts that people will actually go look at the source to verify that fact, here's a basic implementation of an any like interface that will wrap any type with an f() function and allow it to be called:
struct f_any
{
f_any() : ptr() {}
~f_any() { delete ptr; }
bool valid() const { return ptr != 0; }
void f() { assert(ptr); ptr->f(); }
struct placeholder
{
virtual ~placeholder() {}
virtual void f() const = 0;
};
template < typename T >
struct impl : placeholder
{
impl(T const& t) : val(t) {}
void f() const { val.f(); }
T val;
};
// ptr can now point to the entire family of
// struct types generated from impl<T>
placeholder * ptr;
template < typename T >
f_any(T const& t) : ptr(new impl<T>(t)) {}
// assignment, etc...
};
boost::any does the same basic thing except that f() actually returns typeinfo const& and provides other information access to the any_cast function to work.
The key difference between boost::any and boost::variant is that any can store any type, while variant can store only one of a set of enumerated types. The any type stores a void* pointer to the object, as well as a typeinfo object to remember the underlying type and enforce some degree of type safety. In boost::variant, it computes the maximum sized object, and uses "placement new" to allocate the object within this buffer. It also stores the type or the type index.
Note that if you have Boost installed, you should be able to see the source files in "any.hpp" and "variant.hpp". Just search for "include/boost/variant.hpp" and "include/boost/any.hpp" in "/usr", "/usr/local", and "/opt/local" until you find the installed headers, and you can take a look.
Edit
As has been pointed out in the comments below, there was a slight inaccuracy in my description of boost::any. While it can be implemented using void* (and a templated destroy callback to properly delete the pointer), the actualy implementation uses any<T>::placeholder*, with any<T>::holder<T> as subclasses of any<T>::placeholder for unifying the type.
boost::any just snapshots the typeinfo while the templated constructor runs: it has a pointer to a non-templated base class that provides access to the typeinfo, and the constructor derived a type-specific class satisfying that interface. The same technique can actually be used to capture other common capabilities of a set of types (e.g. streaming, common operators, specific functions), though boost doesn't offer control of this.
boost::variant is conceptually similar to what you've done before, but by not literally using a union and instead taking a manual approach to placement construction/destruction of objects in its buffer (while handling alignment issues explicitly) it works around the restrictions that C++ has re complex types in actual unions.

Typecasting from bare data to C++ wrapper

Say I have some data allocated somewhere in my program, like:
some_type a;
and I want to wrap this data in a class for access. Is it valid to say,
class Foo {
private:
some_type _val;
public:
inline void doSomething() { c_doSomething(&_val); }
}
Foo *x = reinterpret_cast<Foo *>(&a);
x->double();
The class has no virtual functions, and only includes a single data item of the type I'm trying to wrap. Does the C++ standard specify that this reinterpret_cast is safe and valid? sizeof(Foo) == sizeof(some_type), no address alignment issues, or anything? (In my case, I'd be ensuring that some_type is either a primitive type like int, or a POD structure, but I'm curious what happens if we don't enforce that restriction, too - for example, a derived class of a UIWidget like a UIMenuItem, or something.)
Thanks!
Is it valid to say...
No, this is not valid. There are only a small number of types that a can be treated as; the complete list can be found in an answer I gave to another question.
Does the C++ standard specify that this reinterpret_cast is safe and valid?
The C++ Standards says very little about reinterpret_cast. Its behavior is almost entirely implementation-defined, so use of it is usually non-portable.
The correct way to do this would be to either
have a Foo constructor that takes a some_type argument and makes a copy of it or stores a reference or pointer to it, or
implement your "wrapper" interface as a set of non-member functions that take a some_type object by reference as an argument.
14882/1998/9.2.17:
"A pointer to a PODstruct
object, suitably converted using a reinterpret_cast, points to its initial
member (or if that member is a bitfield,
then to the unit in which it resides) and vice versa. [Note: There
might therefore be unnamed padding within a PODstruct
object, but not at its beginning, as necessary to
achieve appropriate alignment. ]"
So, it would be valid if your wrapper was strictly a POD in itself. However, access specifiers mean that it is not a strictly a POD. That said, I would be interested in knowing whether any current implementation changes object layout due to access specifiers. I think that for all practical purposes, you are good to go.
And for the case when the element is not a POD, it follows that the container is not a POD, and hence all bets are off.
Since your Foo object is already only valid as long as the existing a is valid:
struct Foo {
some_type &base;
Foo(some_type &base) : base (base) {}
void doSomething() { c_doSomething(&base); }
}
//...
Foo x = a;
x.doSomething();
You want to look up the rules governing POD (plain old data) types. If the C++ class is a POD type, then yes, you can cast it.
The details of what actually happens and how aliasing is handled are implementation defined, but are usually reasonable and should match what would happen with a similar C type or struct.
I happen to use this a lot in a project of mine that implements B+ trees in shared memory maps. It has worked in GCC across multiple types of Linux and BSDs including Mac OS X. It also works fine in Windows with MSVC.
Yes, this is valid as long as the wrapper type you are creating (Foo in your example) is a POD-type.

will compiler reserve memory for this object?

I have following two classes:
template <size_t size>
class Cont{
public:
char charArray[size];
};
template <size_t size>
class ArrayToUse{
public:
Cont<size> container;
inline ArrayToUse(const Cont<size+1> & input):container(reinterpret_cast<const Cont<size> &>(input)){}
};
I have three following lines of code at global scope:
const Cont<12> container={"hello world"};
ArrayToUse<11> temp(container);
char (&charArray)[11]=temp.container.charArray;
In totality of my code The only usage of "container" object is for initialization of an object of "ArrayToUse" class as mentioned and after initialization of "charArray" reference to "temp.container.charArray" I'll use that reference in rest of my code, now I'm wondering does compiler reserve memory for "container" object since that's got a temporary usage?
Any variable defined at global scope has memory reserved for it at compile time. That does not mean it's guaranteed to be properly initialized, but it's there all the same.
At link-time, Visual C++ offers the option to strip unused data and functions via /OPT - see here.
it totaly depends on your particular compiler so i'd say inspect the assembly and find out!
the compiler could optimize container out, or it could neglect to do so.
The compiler should create the container variable in the compiled object file. The linker is the one that can tell if it's needed or not (for an exported symbol, or from another compilation unit if declared extern).
But...
The type Cont<x> is unrelated to Cont<x+1>. You cannot depend on the memory of a member variable being layed out in similar fashions. Heck, you cannot even know if it looks the same, since there is this thing called 'template specialization':
// your code
template <size_t size>
class Cont{
public:
char charArray[size];
};
// my evil tweak
// I'm the worst compiler ever but I feel that this
// array would better be represented as a map...
template<> class Cont<12> {
std::map<int,char> charArray;
};
// your screwed up result
Cont<12> c12;
Cont<11>& c11( reinterpret_cast<Cont<11>&>(c12) );
char (&s11)[11] = c11.charArray; // points to the first byte of a list object...
EDIT -- #UncleBen's comment insinuates I'm overdoing here. And he's right.
according to wikipedia,
A pointer to a POD-struct
object, suitably converted using a
reinterpret cast, points to its
initial member and vice versa,
implying that there is no padding at
the beginning of a POD-struct.
So in this case,
where the charArray is the first member of a Cont<n>, and there are no non-POD members
there is no assignment operator, nor a destructor
It is safe.

Is it possible to declare void pointer to a template function in C++?

Is it possible?
If as I have understood is correct, void pointer can point to any type. Therefore, a template function (undeclared type) is possible? or void pointer is only reserve for "variable" not function? Then what about void function pointer?
You can cast any function pointer type to any other, but you'd better cast it to the right type before you call it. You can therefore use void(*)() as an equivalent to void* for function pointers. This also works with function templates.
template<typename T>
void f(T){}
typedef void(*voidfp)();
voidfp fp=static_cast<voidfp>(&f<int>); // store address of f(int) in variable
static_cast<void(*)(int)>(fp)(3); // call the function
fp=static_cast<voidfp>(&f<std::string>); // store address of f(std::string) in variable
static_cast<void(*)(std::string)>(fp)("hello"); // call the function
According to the Standard, a void* is not required to be able to hold a function pointer. (It is required to hold a pointer to any kind of data). However, most cpu architectures you're likely to see these days have data pointers & function pointers that are the same size.
There is an issue here, because of the words used I am afraid.
There is a difference between pointers and function pointers, most notably they need not be the same size.
Therefore it is undefined behavior to use void* type to hold the address of a function pointer.
In general it is not a good idea in C++ to use void*. Those are necessary in C because of the lack of a proper type system but C++ type system is much more evolved (even though not as evolved as recent languages).
You could probably benefit from some objectification here. If you make your method an instance of a class (template) you can have this class derived from a common base class. This is quite common, those objects are called Functors.
However, without a precise description of your issue, it'll be hard to help more.
to do this with templates you need some trickery, else the compiler cannot disambiguate the function (this is really not recommended, its horrible to read, and probably violates a few thousand porgamming best practices)
IE: this does not work (atleast under VS08 & GCC 3.5):
template <typename tType> tType* GetNULLType()
{
return static_cast<tType*>(0);
}
void* pf = static_cast<void*>(GetNULLType<int>);
you instead need to do:
template <typename tType> tType* GetNULLType()
{
return static_cast<tType*>(0);
}
typedef int* (*t_pointer)();
t_pointer pfGetNull = GetNULLType<int>;
void* pfVoid = (void*)(pfGetNull);
(and before purists moan, it seems C++ style 'safe' casting will not allow this)