Consider the following C++11 code:
#include <type_traits>
struct bar
{
virtual void do_bar() const {}
};
struct foo
{
std::aligned_storage<sizeof(bar),alignof(bar)>::type m_storage;
};
bar is not standard layout because of the virtual function do_bar(). However, foo is standard layout as the type provided by std::aligned_storage is a POD type and foo satisfies all the other requirements for standard layout types.
What happens then when I use the m_storage storage with placement new to construct an instance of bar? E.g.,
foo f;
::new(static_cast<void *>(&f.m_storage)) bar();
Is this legal? Can I use this to cheat my way around restrictions about standard layout types?
Here's your code again:
struct bar {
virtual void do_bar() const {}
};
struct foo {
std::aligned_storage<sizeof(bar), alignof(bar)>::type m_storage;
};
This is fine. struct foo is a standard-layout type, and, given an instance foo myFoo, you can construct an object of type bar into myFoo.m_storage.
However, this is completely pointless from the compiler's POV, so why bother with it? As #dyp wisely said in the comments, "Why do you want foo to be standard-layout?"
You handwaved something about unions. Well, that's fine. You can write this:
union DoesntWork {
bar b; // compiler error in C++11 due to non-standard-layout type
int i;
};
union DoesWork {
foo f; // works fine in C++11, of course
int i;
};
However, equally obviously, you cannot expect this to work:
struct car {
int initialsequence;
};
struct bar {
int initialsequence;
virtual void do_bar() const {}
};
struct foo {
std::aligned_storage<sizeof(bar), alignof(bar)>::type m_storage;
bar& asBar() { return *reinterpret_cast<bar*>(&m_storage); }
};
union JustSilly {
foo f;
car c;
} js;
assert(&js.c.initialsequence == // Fails, because no matter how many
&js.f.asBar().initialsequence); // casts you add, bar still has a vptr!
In other words, you're free to lie to the compiler (via type-punning and reinterpret_cast), but that doesn't make your lies true. ;)
See also: XY problem.
Tried in OSX's XCode C++11 compiler option, and seems to work for me. Of course, you probably want to do "::new(static_cast(&f.m_storage)) bar();" in foo's constructor and invoke its destructor in foo's destructor.
When working with aligned quantities
1) It is advisable to specify alignment for the class or struct using declspec(align(16)) or __attribute((aligned(16))). I have encounter some errors when enabling optimization using VS2010, when I didn't do this.
2) I usually avoid overloading new and use the placement operator like you suggest, e.g.
#include <new> // Remember this otherwise the placement operator is not defined
SomeClass* c = (SomeClass*) _mm_malloc(sizeof(SomeClass),16);
new c SomeClass(); // This is perfectly legal
// Some work
_mm_free(c);
3) A good rules of thumb is to place aligned quantities at the start of your struct or class. This way the compiler won't do zero-padding in between members and warn about this.
Related
I am in the process of converting some legacy code to take advantage of smart pointers in C++. However, I ran into a runtime issue that I'm struggling to figure out. I have code such as the following:
struct foo {
int field;
};
class SomeClass {
private:
std::unique_ptr<foo> m_Foo;
int m_Field;
public:
SomeClass(std::unique_ptr<int> ctorArg)
: m_Field(ctorArg->field), m_Foo(std::move(ctorArg)) {
}
};
std::unique_ptr<foo> fooPtr{ new foo() };
auto const classInstance{ std::make_unique<SomeClass>(std::move(fooPtr)) };
If I put a breakpoint prior to calling the SomeClass constructor, I can verify that fooPtr is not null. However, once I am within the SomeClass constructor, the application is crashing when trying to initialize m_Field, since ctorArg is null (empty). Is this expected? If I change the constructor signature to take std::unique_ptr<int> &&, I see the same issue. Can someone please explain what the issue is with this code, and how to go about fixing it?
The order of member-initializer-list is irrelevant, the members will be initialized in the order of their declaration.
So, first m_Foo(std::move(ctorArg)) will zero out ctorArg then m_Field(ctorArg->field) will attempt to derefence an empty ctorArg.
Change your code to:
class SomeClass {
private:
std::unique_ptr<foo> m_Foo;
int m_Field;
public:
SomeClass(std::unique_ptr<int> ctorArg)
: m_Foo(std::move(ctorArg)), m_Field(m_Foo->field) {
}
};
That is, always mention initializers in the order the fields are declared, and don't use input arguments which have been moved-out from.
I would like to know if my following use of reinterpret_cast is undefined behaviour.
Given a template aggregate such as ...
template<typename T>
struct Container
{
Container(T* p) : ptr(p) { }
...
T* ptr;
};
... and a type hierarchy like ...
struct A { };
struct B : A { };
Is the following cast safe, given that B is a dynamic type of A ...
Container<B>* b = new Container<B>( new B() );
Container<A>* a = reinterpret_cast<Container<A>*>(b);
... in so far as that I can now safely use a->ptr and its (possibly virtual) members?
The code where I use this compiles and executes fine (Clang, OS X) but I'm concerned that I've placed a ticking bomb. I guess every instance of Container<T> shares the same layout and size so it shouldn't be a problem, right?
Looking at what cppreference.com says about reinterpret_cast, there seems to be a statement for legal use that covers what I'm trying to do ...
Type aliasing
When a pointer or reference to object of type T1 is reinterpret_cast (or C-style cast) to a pointer or reference to object of a different type T2, the cast always succeeds, but the resulting pointer or reference may only be accessed if both T1 and T2 are standard-layout types and one of the following is true:
...
T2 is an aggregate type or a union type which holds one of the aforementioned types as an element or non-static member (including, recursively, elements of subaggregates and non-static data members of the contained unions): this makes it safe to cast from the first member of a struct and from an element of a union to the struct/union that contains it.
I appreciate that it looks like I'm going the wrong way about this. That's not what I'm concerned about. I'd just like to know if what I'm doing is safe / legal or not. Thanks in advance for any help.
there seems to be a statement for legal use that covers what I'm trying to do ...
That's not what that exception says or means. That exception says that given
struct S { int i; } s;
you can use *reinterpret_cast<int *>(&s) to access s.i.
There is no similar exception for what you're trying to do. What you're trying to do is simply not valid in C++. Even the below is invalid:
struct S { int i; };
struct T { int i; };
int f(S s) { return ((T &) s).i; }
and compilers optimise based on the assumption that you don't write code like that.
For an actual example that fails at run-time with a current compiler:
#include <cstdlib>
struct S { int i; };
struct T { int i; };
void f(S *s, T *t) { int i = s->i; t->i++; if (s->i == i) std::abort(); }
Here, GCC optimises away the check s->i == i (GCC 4.9.2, with -O2 in the command-line options), and unconditionally calls std::abort(), because the compiler knows that s and t cannot possibly point to the same region of memory. Even though you might try to call it as
int main() { S s = { 0 }; f(&s, reinterpret_cast<T *>(&s)); }
Whether or not the type aliasing is legal according to the standard, you may have other issues.
I guess every instance of Container<T> shares the same layout and
size so it shouldn't be a problem, right?
Actually, not every instance of Container<T> shares the same layout! As explained in this question, template members are only created if they are used, so your Container<A> and Container<B> might have different memory layouts if different members are used for each type.
I have a C library that has types like this:
typedef struct {
// ...
} mytype;
mytype *mytype_new() {
mytype *t = malloc(sizeof(*t));
// [Initialize t]
return t;
}
void mytype_dosomething(mytype *t, int arg);
I want to provide C++ wrappers to provide a better syntax. However, I want to avoid the complication of having a separately-allocated wrapper object. I have a relatively complicated graph of objects whose memory-management is already more complicated than I would like (objects are refcounted in such a way that all reachable objects are kept alive). Also the C library will be calling back into C++ with pointers to this object and the cost of a new wrapper object to be constructed for each C->C++ callback (since C doesn't know about the wrappers) is unacceptable to me.
My general scheme is to do:
class MyType : public mytype {
public:
static MyType* New() { return (MyType*)mytype_new(); }
void DoSomething(int arg) { mytype_dosomething(this, arg); }
};
This will give C++ programmers nicer syntax:
// C Usage:
mytype *t = mytype_new();
mytype_dosomething(t, arg);
// C++ Usage:
MyType *t = MyType::New();
t->DoSomething(arg);
The fib is that I'm downcasting a mytype* (which was allocated with malloc()) to a MyType*, which is a lie. But if MyType has no members and no virtual functions, it seems like I should be able to depend on sizeof(mytype) == sizeof(MyType), and besides MyType has no actual data to which the compiler could generate any kind of reference.
So even though this probably violates the C++ standard, I'm tempted to think that I can get away with this, even across a wide array of compilers and platforms.
My questions are:
Is it possible that, by some streak of luck, this does not actually violate the C++ standard?
Can anyone think of any kind of real-world, practical problem I could run into by using a scheme like this?
EDIT: #James McNellis asks a good question of why I can't define MyType as:
class MyType {
public:
MyType() { mytype_init(this); }
private:
mytype t;
};
The reason is that I have C callbacks that will call back into C++ with a mytype*, and I want to be able convert this directly into a MyType* without having to copy.
You're downcasting a mytype* to a MyType*, which is legal C++. But here it's problematic since the mytype* pointer doesn't actually point to a MyType. It actually points to a mytype. Thus, if you downcast it do a MyType and attempt to access its members, it'll almost certainly not work. Even if there are no data members or virtual functions, you might in the future, and it's still a huge code smell.
Even if it doesn't violate the C++ standard (which I think it does), I would still be a bit suspicious about the code. Typically if you're wrapping a C library the "modern C++ way" is through the RAII idiom:
class MyType
{
public:
// Constructor
MyType() : myType(::mytype_new()) {}
// Destructor
~MyType() { ::my_type_delete(); /* or something similar to this */ }
mytype* GetRawMyType() { return myType; }
const mytype* GetConstRawMyType() const { return myType; }
void DoSomething(int arg) { ::mytype_dosomething(myType, int arg); }
private:
// MyType is not copyable.
MyType(const MyType&);
MyType& operator=(const MyType&);
mytype* myType;
};
// Usage example:
{
MyType t; // constructor called here
t.DoSomething(123);
} // destructor called when scope ends
Is it possible that, by some streak of luck, this does not actually violate the C++ standard?
I'm not advocating this style, but as MyType and mytype are both PODs, I believe the cast does not violate the Standard. I believe MyType and mytype are layout-compatible (2003 version, Section 9.2, clause 14: "Two POD-struct ... types are layout-compatible if they have the same number of nonstatic data members, and corresponding nonstatic data members (in order) have layout-compatible types (3.9)."), and as such can be cast around without trouble.
EDIT: I had to test things, and it turns out I'm wrong. This is not Standard, as the base class makes MyType non-POD. The following doesn't compile:
#include <cstdio>
namespace {
extern "C" struct Foo {
int i;
};
extern "C" int do_foo(Foo* f)
{
return 5 + f->i;
}
struct Bar : Foo {
int foo_it_up()
{
return do_foo(this);
}
};
}
int main()
{
Bar f = { 5 };
std::printf("%d\n", f.foo_it_up());
}
Visual C++ gives the error message that "Types with a base are not aggregate." Since "Types with a base are not aggregate," then the passage I quoted simply doesn't apply.
I believe that you're still safe in that most compilers will make MyType layout-compatible with with mytype. The cast will "work," but it's not Standard.
I think it would be much safer and elegant to have a mytype* data member of MyType, and initialize it in the constructor of MyType rather than having a New() method (which, by the way, has to be static if you do want to have it).
It does violate the c++ standard, however it should work on most (all that I know) compilers .
You're relying on a specific implementation detail here (that the compiler doesn't care what the actual object is, just what is the type you gave it), but I don't think any compiler has a different implementation detail. be sure to check it on every compiler you use, it might catch you unprepared.
I want to initialize constant in child-class, instead of base class. And use it to get rid of dynamic memory allocation (I know array sizes already, and there will be a few child-classes with different constants).
So I try:
class A {
public:
const int x;
A() : x(0) {}
A(int x) : x(x) {}
void f() {
double y[this->x];
}
};
class B : A {
B() : A(2) {}
};
Pretty simple, but compiler says:
error C2057: expected constant expression
How can I say to compiler, that it is really a constant?
It isn't a constant though. It can still be modified by the constructor. Only a compile time constant is allowed for the size of an array. When the compiler says "constant expression", it is not meaning an expression which returns a constant value, but an constant, such as "52" or "45" or something along those lines.
Use std::vector instead.
EDIT: In response to "I know array sizes already, and there will be a few child-classes with different constants"
The only way to do that is to use a template.
template<size_t x>
class A {
public:
void f() {
double y[x];
}
};
typedef A<2> B;
The behaviour you expect could be achieved using the following template.
Note that this is actually unreliable, disgusting and could be used only as "a sample". Use std::vector instead.
template <size_t a = 0>
class A {
public:
A() { }
void f() {
int y[a];
y[0] = 5;
}
};
class B : A<2> {
B() { }
};
void main() {
A<1> a;
a.f();
// Undefined behaviour - creating an array of size 0
// At least, MSVS2008 treats it as an error :)
// A<0> a_;
}
There's "constant", and then there's "constant". If you want to allocate an array on the stack like that, the compiler needs the length of the array at compile time, and based on what you've given there it can't figure that out. Interestingly, gcc supports an extension (not supported in standard C++) that allows for stack allocation for variable lengths.
I don't know if it will work for your purposes, but one possibility would be to make it a template parameter:
template <int size>
class A {
double y[size];
};
In this case, you'd probably want to create an instance of A in B instead of using inheritance.
The other obvious possibility would be to use a tr1::array object instead. This is is also a template, so the idea is pretty much the same, but it's already written, tested and working so you can avoid all that. If your compiler doesn't supply TR1 classes, Boost has a mostly conforming implementation (boost::array).
In C++ it is possible to create a struct:
struct MyStruct
{
...
}
And also possible to do the following:
typedef struct
{
...
} MyStruct;
And yet as far as I can tell, no discernable difference between the two. Which is preferable? Why do both ways exist if there is no difference? Is one better than the other in style or readability?
Here are the differences between the two declarations/definitions:
1) You cannot use a typedef name to identify a constructor or a destructor
struct MyStruct { MyStruct(); ~MyStruct(); }; // ok
typedef struct { MyStructTD(); ~MyStructTD(); } MyStructTD; // not ok
// now consider
typedef struct MyStruct2 { MyStruct2(); } MyStructTD2; // ok
MyStructTD2::MyStruct2() { } // ok
MyStructTD2::MyStructTD2() { } // not ok
2) You cannot hide a typedef name like you can a name introduced via the class-head - or conversely if you already have a function or an object with a certain name, you can still declare a class with that name using the class-head but not via the typedef approach.
struct MyStruct { }; // ok
typedef struct { } MyStructTD; // ok
void MyStruct() { } // (1) - ok Hides struct MyStruct
void MyStructTD() { } // (2) - not-ok - ill-formed
//> Or if you flip it around, consider in a new translation unit:
void MyStruct() { } // ok
void MyStructTD() { } // ok
struct MyStruct { }; // ok
typedef struct { } MyStructTD; // Not ok
3) You cannot use a typedef name in an elaborated type specifier
struct MyStruct { }; // ok
typedef struct { } MyStructTD; // ok
int main()
{
void MyStruct();
void MyStructTD(); // ok - new declarative region
struct MyStruct ms; // ok - names the type
struct MyStructTD ms2; // not ok - cannot use typedef-name here
}
struct AnotherStruct
{
friend struct MyStruct; // ok
friend struct MyStructTD; // not ok
};
4) You cannot use it to define nested structs
struct S { struct M; };
typedef struct { } S::M; // not ok
struct S::M { }; // ok
As you can see, there is a discernible difference between the two. Some of the quirks of typedefs are a result of C compatibility (which is mainly why both ways exist i believe) - and in most cases, declaring the name in the class-head is more natural C++ - it has its advantages (especially when you need to define constructors and destructors), and is therefore preferable. If you are writing code that needs to be C and C++ compatible, then there is benefit to using both approaches. But if you are writing pure C++, I find specifying the class name in the class-head to be more readable.
The typedef version is a special case of
typedef foo bar;
which defines a new "type" bar as an alias for foo. In your case, foo happens to be a struct. In C, this was the only way to introduce new "types" (in quotes, because they are not really equivalent to int, float and co). In C++, this is not so useful, because C++ was designed to make definition of new types easier and more complete than C (at least at the beginnings of C++), and the typedef is not even necessary to refer to a previously declared struct (or class).
The latter is there for compatibility with C - use the first in new C++ code.
You would use a typedef so you do not need to specify the struct keyword when declaring variables of that struct.
Without typedef:
struct MyStruct foo;
With typedef:
MyStruct foo;
Basically you are making MyStruct appear as a new type so it also implements some level of type abstraction as programmers do not need to know explicitly what type it is. You can pass MyStruct into a function, manipulate the data in it and return it and the programmer need never worry about what actually happens.
Much of the C standard library uses typedefs for this reason.
The "struct MyStruct { };" construct implicitly defines the equivalent typedef, so typically that would be the preferred modern usage. There are still some uses for a typedef, mainly with pointer types to structures. E.g.
typedef struct MyStruct* MyStructPtr;
There are many answers that consider both approaches as equivalent, but they are not.
The typedef keyword is used to create a type alias, that is, it provides a new way of referring to another type. When you use typedef struct {} XXX; you are actually creating an unnamed type and then creating an alias XXX to that unnamed type. On the other hand, when you type struct XXX {}.
Please, read the answer by Michael Burr here (which is a better answer than the one accepted for that question.