I am working on an application which in my opinion is rather poorly designed but that's another issue. There is a simple class in that app that I need to add a variable to. In this case I would like to add a STL stack to the class. Should be simple except that elsewhere the same class is used within a union and the compiler then complains that the class has a copy constructor. If I remove my added variable it compiles fine. My first thought was to add the stack as a pointer and then initialise it in the constructor but then the compiler complains that the class has a non trivial constructor.
My second (not ideal) thought was to add it as a pointer and initialise it outside the class. I know this isn't a good solution but I am up against some poorly designed code here which I cannot rewrite. However, this won't work because where I would need to initialise it, I cannot know if it has already been initialised or not. I cannot initialise the pointer in the class to NULL as even just doing that makes the compiler complain that the class now has a non-trivial constructor.
I guess my question is two-fold. Is there a way of adding a STL stack to a class that is used in a union? If not, is there a way of initialising a pointer to NULL in a class that is used in a union?
The class and union look something like this:
class MyClass
{
public:
std::stack<short> Index; // ideally what I wanted
}
union
{
int nNum;
MyClass myclass;
} u;
Please note: I cannot change the union. I accept that I cannot do what I was thinking. Is there any alternative no matter how silly it might sound. I cannot change the union or redesign the app as much as I would like to. This is the problem when you work on large apps that were first written around 18 years ago.
You could define the union as
union
{
int nNum;
MyClass * myclass;
} u;
This has the added benefit that int and pointer are the same size and it compiles.
Also, your example won't compile. It's missing ';' at the end of the class.
The answer for both questions is NO for C++03.
Since
9.5 Unions [class.union]
1
...
An object of a class with a non-trivial default constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor
can an array of such objects. If a union contains a static data member, or a member of reference type,
the program is ill-formed.
You still can add constructor to the union that will init pointer instead of class ctor.
In C++11 however you can provide your own constructors for union, that should implement correct way to copy classes with non trivial constructors.
9.5 Unions [class.union]
2 A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class. If a union contains a non-static data member of reference type the program is ill-formed. At most one non-static data member of a union may have a brace-or-equal-initializer. [Note: If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be
user-provided or it will be implicitly deleted (8.4.3) for the union. — end note ]
You may also be interested in a following article
http://cpp11standard.blogspot.com/2012/11/c11-standard-explained-1-unrestricted.html
Related
In a C++ project that is full of objects (with proper behaviors) and relatively few of non-object-oriented structs (consisting of only data fields and no methods), I would like to prevent the accidental misuse of these structs, in which one might try to create a class inheriting from it.
According to my understanding, because these "POD" (plain old data) structs do not have a virtual destructor, it is not possible to properly delete a derived class object (if one is allowed to create it) via a pointer of the POD type.
This seems to make a good use case for the C++11 "final" keyword, which marks a class or struct as non-inheritable.
However, I wonder if the "final" keyword causes the struct to become non-POD?
I suspect that the standards documentation may have addressed this issue, but I am not intelligent enough to sift through the very long documentations to find out. Any useful pointers would be welcome.
Note: I am not interested in merely knowing that it passes the compilation of some compiler vendors. Passing compilation do not guarantee:
Whether the compiled code will execute correctly in all situations (especially when the technique is applied in a larger, more complex project),
Whether the C++ standards body intends this to be used in this way.
#include <iostream>
using namespace std;
struct Pod final
{
int a;
int b;
int c;
};
#if 0
class FailsBecauseCannotDeriveFromFinalAnything : public Pod
{
};
#endif
class ContainsSomethingFinalAsMember
{
public:
ContainsSomethingFinalAsMember() : pod() {}
private:
Pod pod;
};
int main()
{
std::cout << std::is_pod < Pod > :: value << std::endl;
return 0;
}
According to my understanding, because these "POD" (plain old data) structs do not have a virtual destructor, it is not possible to properly delete a derived class object (if one is allowed to create it) via a pointer of the POD type.
It's not possible given a raw pointer, but it is possible given a smart pointer object, such as std::shared_ptr or a std::unique_ptr with an appropriate deleter.
Since smart pointers were standardized, there are few excuses to continue following the poor practice of using the delete operator manually. Certainly, classes shouldn't be designed around compatibility with the delete operator. Each class interface should be designed with its particular uses in mind.
No, it's not a good practice to make every class either final or polymorphic.
However, I wonder if the "final" keyword causes the struct to become non-POD?
No, it's still POD. The requirements for POD are standard layout (in turn requiring no base class, no access specifiers between members, no virtual anything) and trivial special member functions (copy/move constructor, assignment operator, destructor).
However, the purpose of POD-ness is to allow you to use memcpy instead of properly constructing objects, which good C++ code would avoid doing.
Marking a class final does not change its POD status. Quoting C++11:
9 [class]:
6 A trivially copyable class is a class that:
has no non-trivial copy constructors (12.8),
has no non-trivial move constructors (12.8),
has no non-trivial copy assignment operators (13.5.3, 12.8),
has no non-trivial move assignment operators (13.5.3, 12.8), and
has a trivial destructor (12.4).
A trivial class is a class that has a trivial default constructor (12.1) and is trivially copyable.
[ Note: In particular, a trivially copyable or trivial class does not have virtual functions or virtual base
classes.—end note ]
7 A standard-layout class is a class that:
has no non-static data members of type non-standard-layout class (or array of such types) or reference,
has no virtual functions (10.3) and no virtual base classes (10.1),
has the same access control (Clause 11) for all non-static data members,
has no non-standard-layout base classes,
either has no non-static data members in the most derived class and at most one base class with
non-static data members, or has no base classes with non-static data members, and
has no base classes of the same type as the first non-static data member.
8 A standard-layout struct is a standard-layout class defined with the class-key struct or the class-key class. ...
10 A POD struct is a non-union class that is both a trivial class and a standard-layout class, and has no
non-static data members of type non-POD struct, non-POD union (or array of such types). ...
12.1 [class.ctor]
5 ... A default constructor is trivial if it is not user-provided and if:
its class has no virtual functions (10.3) and no virtual base classes (10.1), and
no non-static data member of its class has a brace-or-equal-initializer, and
all the direct base classes of its class have trivial default constructors, and
for all the non-static data members of its class that are of class type (or array thereof), each such class
has a trivial default constructor.
Otherwise, the default constructor is non-trivial.
12.4 [class.dtor]
5 ... A destructor is trivial if it is not user-provided and if:
the destructor is not virtual,
all of the direct base classes of its class have trivial destructors, and
for all of the non-static data members of its class that are of class type (or array thereof), each such
class has a trivial destructor.
Otherwise, the destructor is non-trivial.
12.8 [class.copy]
12 A copy/move constructor for class X is trivial if it is not user-provided and if
— class X has no virtual functions (10.3) and no virtual base classes (10.1), and
— the constructor selected to copy/move each direct base class subobject is trivial, and
— for each non-static data member of X that is of class type (or array thereof), the constructor selected
to copy/move that member is trivial;
otherwise the copy/move constructor is non-trivial.
25 A copy/move assignment operator for class X is trivial if it is not user-provided and if
class X has no virtual functions (10.3) and no virtual base classes (10.1), and
the assignment operator selected to copy/move each direct base class subobject is trivial, and
for each non-static data member of X that is of class type (or array thereof), the assignment operator
selected to copy/move that member is trivial;
otherwise the copy/move assignment operator is non-trivial.
As you see, the definition of a POD struct does not take into account whether the class has the class-virt-specifier final.
In the following fragment of code I receive a compiler error when the method Data::setValue(int, int) is declared virtual:
struct Data{
int ma;
int mb;
virtual void setValues(int a, int b){
ma = a;
mb = b;
}
};
struct ThreadMessage {
enum type {
DATA
};
type msg_type;
union content {
Data d;
int a;
}content;
};
The error that the compiler (g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3) gives me is:
struct.cpp:19:14: error: member 'Data ThreadMessage::content::d' with
constructor not allowed in union
struct.cpp:19:14: error: member 'Data ThreadMessage::content::d' with copy assignment operator not allowed in union
This set of compiler errors took me completely off guard. In the actual code, I had many more attributes and functions. Therefore, I started looking where I put the bloody operator=() and constructor but I didn't write them in struct Data.
I know my problem disappears when I make the Data::setValues as not virtual. But why does the struct Data have a constructor? When exactly does a struct have a constructor in C++? And why does the compilation error disappear when I make virtual void Data::setValues(int, int) non virtual?
Barring the default access of members, a struct and a class are identical in C++.
Unless you program carefully (and have C++11), you cannot have a class or a struct member in a union since there would be ambiguity as to how such members of the union should be constructed.
That's what your compiler is telling you.
You may want to browse through this thread: Struct Constructor in C++?
The Reader's Digest version is that, like classes, structs have a default constructor, which you can overload and define however you like.
The error messages you quoted are misleading, so no doubt you wonder why making the function non-virtual fixes the problem.
First - structs and classes in C++ have constructors and copy assignment operators. If you do not create them yourself, they will be created for you. (You may delete those default versions). In your example there is an automatically generated constructor of Data, and also automatically generated assignment operator.
Now why the error messages are misleading? Because they are not true. In C++ you can have union members with constructors or assignment operators. The problem starts when those member functions are not trivial. Before C++11 it was just not possible to have an union member with non-trivial constructor. C++11 changed it, but still without writing additional functions it is not possible to use such union.
A struct/class with virtual functions has non-trivial member functions as constructor and assignment operator (because hidden data member needs to be managed). This is why when you make the function non-virtual the errors disappear - then the member functions become trivial and your struct may be used as a union member without problems.
When exactly does a struct have a constructor in c++
Always.
The error message is a bit confusing, but it's saying that you cannot have a class there.
A class is a type defined with either the struct keyword or the class keyword.
Every class has a constructor and an assignment operator, whether it's user-provided or not.
The compiler error message is a bit misleading. From the conceptual language point of view your class Data will have a constructor in any case, regardless of whether the function is virtual or not.
The compiler is apparently a pre-C++11 one (or works in pre-C++11 mode). And it does not like the fact that Data's constructor is non-trivial. It is specifically the non-triviality of Data's constructor that makes the compiler to say that Data is a class "with constructor".
In this particular case the constructor becomes non-trivial once you introduce at least one virtual function into the class.
A non-trivial constructor is a constructor that has to do something (in your case - initialize the per-object household information that support polymorphism). I.e. it is a constructor that must exist physically in generated code. Meanwhile a trivial constructor exists only conceptually, but produces no code. The compiler is referring to that physical distinction when it separates classes into ones "with constructor" and ones "without constructor".
I am asked how many members there are in the following class:
class xClass {
private:
int u;
double w;
public:
void func();
void print() const;
xClass();
xClass(int a, double b);
};
i only see 6, but the solution says 9?
This is for C++ 11.
§ 9.2 Class members:
Members of a class are data members, member functions (9.3), ...
§ 12 Special member functions:
The default constructor (12.1), copy constructor and copy assignment operator (12.8), move constructor and move assignment operator (12.8), and destructor (12.4) are special member functions. [Note: The implementation will implicitly declare these member functions ...]
This hints at the fact that special member functions are indeed member functions (unlike the tasmanian tiger, which is not a tiger) and therefore class members in the sense of 9.2.
An implicitly-declared special member function is declared at the closing } of the class-specifier.
This means, special member functions are not added to the class at a later stage (e.g. during compilation); they're there once the class has been defined. Also, special member functions are declared even if they are not used.
To summarize: in C++ 11, there are 11 members. In C++ 03, move constructor and move assignment operator do not exist, so there might be 9 members. However, I did not check the wording for C++ 03, so there might be 6 members.
I read the comments but I have to say that it is difficult to say how many class members in your example. I think that there are some contradictions in the C++ Standard description. For example in section 9.2 Class members there is said
1 The member-specification in a class definition declares the full set
of members of the class; no member can be added elsewhere.
So if to follow the Standard in your example there are indeed only 6 members because only they take part in the member-specification.
Also according to the C++ Standard
Members of a class are data members, member functions (9.3),...
If to look through section 9.3 then we will see that constructors, destructors and copy and move assignment operators are not mentioned there.:) They are called special member functions. But special member functions are not mentioned among member functions.
So you can say bravely that there are only 6 class members. If somebody have questions then let he ask the C++ Standard Committee.:)
I read this article from D. Kalev this morning about the new c++11 feature "defaulted and deleted functions", and can't understand the part about performance, namely:
the manual definition of a special member function (even if it's trivial) is usually less efficient than an implicitly-defined one.
By googling to find an answer, I found another article of the same author:
the synthesized constructor and copy constructor enable the implementation to create code that's more efficient than user-written code, because it can apply optimizations that aren't always possible otherwise.
There is no explication, but I read time to time similar claims.
But how is it that writing:
class C { C() = default; };
can be more efficient than
class C { C(){} };
? I though a compiler would be smart enough to detect such situation and optimize that. In other words how is it easier for the compiler to optimize when it sees =default instead of {} (void body function)?
Edit: the question was edited to add the "c++11" tag, but this question remains in c++03 context: just replace class C {C()=default;}; by class C {};, so not really a c++11 specific question.
You ask, how is it that
class C { C() = default; };
can be more efficient than
class C { C(){} };
Well, both constructors do nothing, so it's meaningless to talk about efficiency for that example.
But more generally, in e.g. a copy constructor one can imagine that copying one POD item at a time will not be recognized as optimizable by simple optimizer, whereas with automatic generation it might just do a memcpy. Who knows. It's a Quality of Implementation issue, and I can easily imagine also the opposite.
So, measure, if it matters.
Cheers & hth.,
It makes no sense whatsoever to talk about "manual definition of a special member function (even if it's trivial)", because user-provided special member functions are, by definition, non-trivial. This non-triviality comes into play when using type traits, and also POD-ness, and many optimizations are only possible with trivial or POD types.
A better restatement of the same quote would be:
The defaulted special member functions enable libraries to detect that calls to these functions may be omitted entirely.
From section 12.1 [class.ctor]
A default constructor is trivial if it
is neither user-provided nor deleted
and if:
its class has no virtual
functions (10.3) and no virtual base
classes (10.1), and
no non-static
data member of its class has a
brace-or-equal-initializer, and
all
the direct base classes of its class
have trivial default constructors, and
for all the non-static data members
of its class that are of class type
(or array thereof), each such class
has a trivial default constructor.
Otherwise, the default constructor is
non-trivial.
From section 12.8 [class.copy]:
A copy/move constructor for class X is
trivial if it is neither user-provided
nor deleted and if
class X has no
virtual functions (10.3) and no
virtual base classes (10.1), and
the constructor selected to copy/move
each direct base class subobject is
trivial, and
for each non-static
data member of X that is of class type
(or array thereof), the constructor
selected to copy/move that member is
trivial;
otherwise the copy/move
constructor is non-trivial.
From section 9, [class]:
A trivially copyable class is a class
that:
has no non-trivial copy
constructors (12.8),
has no
non-trivial move constructors (12.8),
has no non-trivial copy assignment
operators (13.5.3, 12.8),
has no
non-trivial move assignment operators
(13.5.3, 12.8), and
has a trivial
destructor (12.4).
A trivial class is a class that has a
trivial default constructor (12.1) and
is trivially copyable. [ Note: in
particular, a trivially copyable or
trivial class does not have virtual
functions or virtual base classes. —
end note ]
Take performance claims "with a grain of salt".
I've heard a high-rated MIT professor make a claim like that for his favorite thing, and the only reason nobody asked him "why" was because he was a high-rated MIT professor.
Such constructors and destructors might have other advantages, but claims about performance (outside of big-O) are seldom even meaningful except in highly contrived circumstances.
To be honest, I can't see it either.
Among other things, I can see why one should use
class C { C() = default; };
that seems to me the same as
class C { };
Or, if other constructors are provided, as:
class C {
C() {}
// other constructors.
};
I fail to see the real problem the author is writing about here.
class Foo {
Foo(int val) { /* Do some initialization */ }
Foo() { /* Do nothing */ }
};
union Bar {
Foo foo;
};
That code generates this error:
error C2620: member 'Bar::foo' of union 'Bar' has user-defined constructor or non-trivial default constructor
I understand why you'd throw that error if the constructor actually did something, but the constructor here takes no parameters and does nothing. Is there any way I can stuff this class into a union? I've had to resort all the way to doing char foo[sizeof(Foo)] and would like a cleaner solution.
Originally from this question:
Initializing a union with a non-trivial constructor:
From C++03, 9.5 Unions, pg 162
A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class.An object of a class with a non-trivial constructor (12.1), a non-trivial copy constructor (12.8), a non-trivial destructor (12.4), or a non-trivial copy assignment operator (13.5.3, 12.8) cannot be a member of a union, nor can an array of such objects
So, your class is forbidden to be a member of the union.
This isn't allowed in the C++03 standard.
If objects with user defined default constructors were allowed in a union, the compiler couldn't decide which constructor to use, because all refer to the same memory location. Thus, objects with user defined constructors aren't allowed in unions.
The compiler will ignore the fact that your constructor doesn't do anything, because it might be defined elsewhere than the union.
You might get away with a C++0x constructor() = default;
Standard-specialists will likely answer this question more precisely than I do, but if I recall correctly, union members must be of POD type.
Use boost::variant if you want to use non-POD classes inside a union.
If your class has a user defined constructor, destructor or copy constructor, or assignment operator then it cannot be inside of a Union.