What is the need for MaxAlign trick when creating static singleton? - c++

Following a snippet of code from Loki singleton implementation which shows what it calls "MaxAlign Trick". I assume it has something to do with alignment (duh!), but what's the purpose of trying to align with all the types mentioned inside the union? Will the placement new inside Create() break without it?
template <class T> struct CreateStatic
{
union MaxAlign
{
char t_[sizeof(T)];
short int shortInt_;
int int_;
long int longInt_;
float float_;
double double_;
long double longDouble_;
struct Test;
int Test::* pMember_;
int (Test::*pMemberFn_)(int);
};
static T* Create()
{
static MaxAlign staticMemory_;
return new(&staticMemory_) T;
}
// other code...
}

MaxAlign serves two purposes. First, it is an implementation of the C++11 std::max_align_t: "a trivial standard-layout type whose alignment requirement is at least as strict (as large) as that of every scalar type." (cppreference). Since the alignment of a type is the alignment of the data member with the highest alignment requirements, the definition of MaxAlign gives us exactly that: a type that is guaranteed to have the max. alignment for the platform of interest.
Second, it is also a buffer that is large enough to contain a T:
char t_[sizeof(T)];
Taking both aspects, MaxAlign provides the C++11 feature std::aligned_storage_t<size, alignment> (without taking over-alignment of T is into account - it probably didn't even exist back then).
But why is it needed: placement new requires the buffer to be suitably aligned for the instance that is being constructed. Without this "alignment trick", you might end up with undefined behaviour. T being an unkonwn type, Loki circumvents any risks by choosing the maximal alignment for the platform the code is being compiled for.
In modern code, you would probably not use placement new, but use a static object on the stack, e.g.
static T& Create() {
static T instance;
return instance;
}
But 20 years ago, this might not have worked properly across compilers and/or in multi-threaded environments (proper initialisation of T instance in the above is only guaranteed since C++11 IIRC).

Related

std::optional implemented as union vs char[]/aligned_storage

While reading through GCC's implementation of std::optional I noticed something interesting. I know boost::optional is implemented as follows:
template <typename T>
class optional {
// ...
private:
bool has_value_;
aligned_storage<T, /* ... */> storage_;
}
But then both libstdc++ and libc++ (and Abseil) implement their optional types like this:
template <typename T>
class optional {
// ...
private:
struct empty_byte {};
union {
empty_byte empty_;
T value_;
};
bool has_value_;
}
They look to me as they are functionally identical, but are there any advantages of using one over the other? (Except for the obvious lack of placement new in the latter which is really nice.)
They look to me as they are functionally identical, but are there any advantages of using one over the other? (Except for the obvious lack placement new in the latter which is really nice.)
It's not just "really nice" - it's critical for a really important bit of functionality, namely:
constexpr std::optional<int> o(42);
There are several things you cannot do in a constant expression, and those include new and reinterpret_cast. If you implemented optional with aligned_storage, you would need to use the new to create the object and reinterpret_cast to get it back out, which would prevent optional from being constexpr friendly.
With the union implementation, you don't have this problem, so you can use optional in constexpr programming (even before the fix for trivial copyability that Nicol is talking about, optional was already required to be usable as constexpr).
std::optional cannot be implemented as aligned storage, due to a post-C++17 defect fix. Specifically, std::optional<T> is required to be trivially copyable if T is trivially copyable. A union{empty; T t}; will satisfy this requirement
Internal storage and placement-new/delete usage cannot. Doing a byte copy from a TriviallyCopyable object to storage that does not yet contain an object is not sufficient in the C++ memory model to actually create that object. By contrast, the compiler-generated copy of an engaged union over TriviallyCopyable types will be trivial and will work to create the destination object.
So std::optional must be implemented this way.

Variable class/struct structure? (Not template & not union?)

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.

Placement new based on template sizeof()

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.

Decent way to disallow virtual functions due to placement new usage

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.

char array as storage for placement new

Is the following legal C++ with well-defined behaviour?
class my_class { ... };
int main()
{
char storage[sizeof(my_class)];
new ((void *)storage) my_class();
}
Or is this problematic because of pointer casting/alignment considerations?
Yes, it's problematic. You simply have no guarantee that the memory is properly aligned.
While various tricks exist to get storage with proper alignment, you're best off using Boost's or C++0x's aligned_storage, which hide these tricks from you.
Then you just need:
// C++0x
typedef std::aligned_storage<sizeof(my_class),
alignof(my_class)>::type storage_type;
// Boost
typedef boost::aligned_storage<sizeof(my_class),
boost::alignment_of<my_class>::value>::type storage_type;
storage_type storage; // properly aligned
new (&storage) my_class(); // okay
Note that in C++0x, using attributes, you can just do this:
char storage [[align(my_class)]] [sizeof(my_class)];
As people have mentioned here, this won't necessarily work due to alignment restrictions. There are several ways to get the alignment right. First, if you have a C++0x-compliant compiler, you can use the alignof operator to try to force the alignment to be correct. Second, you could dynamically-allocate the character array, since memory from operator new is guaranteed to be aligned in such a way that anything can use it correctly. Third, you could try storing the character array in a union with some type that has the maximum possible alignment on your system; I believe that this article has some info on it (though it's designed for C++03 and is certainly not as good as the alignof operator that's coming out soon).
Hope this helps!
It is at least problematic due to alignment.
On most Non-Intel architecture the code will generate a "bus error" due to wrong alignment or be extremely slow because of processor traps needed to fix the unaligned memory access.
On Intel architecture this will normally just be a bit slower than usual. Except if some SSE operations are involved, then it may also crash.
In case anyone wants to avoid Boost or C++1x, this complete code works both in GCC and MSVC. The MSVC-specific code is based on Chromium's aligned_memory.h. It's a little more complex than the GCC version, because MSVC's __declspec(align(.)) only accepts literal alignment values, and this is worked around using template specialization for all possible alignments.
#ifdef _MSC_VER
template <size_t Size, size_t Align>
struct AlignedMemory;
#define DECLARE_ONE_ALIGNED_MEMORY(alignment) \
template <size_t Size> \
struct __declspec(align(alignment)) AlignedMemory<Size, alignment> { \
char mem[Size]; \
};
DECLARE_ONE_ALIGNED_MEMORY(1)
DECLARE_ONE_ALIGNED_MEMORY(2)
DECLARE_ONE_ALIGNED_MEMORY(4)
DECLARE_ONE_ALIGNED_MEMORY(8)
DECLARE_ONE_ALIGNED_MEMORY(16)
DECLARE_ONE_ALIGNED_MEMORY(32)
DECLARE_ONE_ALIGNED_MEMORY(64)
DECLARE_ONE_ALIGNED_MEMORY(128)
DECLARE_ONE_ALIGNED_MEMORY(256)
DECLARE_ONE_ALIGNED_MEMORY(512)
DECLARE_ONE_ALIGNED_MEMORY(1024)
DECLARE_ONE_ALIGNED_MEMORY(2048)
DECLARE_ONE_ALIGNED_MEMORY(4096)
#else
template <size_t Size, size_t Align>
struct AlignedMemory {
char mem[Size];
} __attribute__((aligned(Align)));
#endif
template <class T>
struct AlignedMemoryFor : public AlignedMemory<sizeof(T), __alignof(T)> {};
The char array may not be aligned correctly for the size of myclass. On some architectures, that means slower accesses, and on others, it means a crash. Instead of char, you should use a type whose alignment is equal to or greater than that of the struct, which is given by the largest alignment requirement of any of its members.
#include <stdint.h>
class my_class { int x; };
int main() {
uint32_t storage[size];
new(storage) my_class();
}
To allocate enough memory for one my_class instance, I think size ought to be sizeof(my_class) / sizeof(T), where T is whichever type you use to get the correct alignment.