Isn't using uniform initialization dangerous? - c++11

I discovered uniform initialization a few days ago, and I see about everywhere that everyone should use it as much as possible.
However, I can't help thinking that this new syntax is more trouble than it's worth...
First example
Suppose I write a library, in which I have a struct like this:
struct MyStruct
{
int member0;
int member1;
}
A user could write something like this using aggregate initialization :
MyStruct myVar = {0, 1}; // member0 = 0 and member1 = 1
Now, let us say that I update my library, and that the struct now looks like this :
struct MyStruct
{
int member0;
int member1;
MyStruct(int p0, int p1) : member0(p1), member1(p0){}
}
Before C++11, the user code would stop compiling, which would force the user to rewrite his code and use the constructor. But now, the code will compile and be interpreted as uniform initialization :
MyStruct myVar = {0, 1}; // member0 = 1 and member1 = 0
Without the user knowing, updating his library will make his code do something very different!
Second example
Now, let us say that I have a class like this in my library :
class MyClass
{
public:
MyClass(int size, int default = 0) : elements(size, default){}
private:
std::vector<int> elements;
}
A user can use it like this :
MyClass myVar (3,1); // 3 elements with value 1
or, using uniform initilization, like this :
MyClass myVar {3,1}; // 3 elements with value 1
Then again, let us say that I update my library. The class now look like this :
class MyClass
{
public:
MyClass(int size, int default = 0) : elements(size, default){}
MyClass(std::initializer_list<int> elts) : elements(elts){}
private:
std::vector<int> elements;
}
There won't be a problem if a classic constructor was used :
MyClass myVar (3,1); // 3 elements with value 1
but the code interpretation will change if uniform initialization was called :
MyClass myVar {3,1}; // 2 elements with values 3 and 1
Based on these examples, it seems to me to be extremely dangerous for a user to use uniform initialization, since the code interpretation may change when things are added to the used libraries, without any warning at all.
Worse, the introduction of uniform initialization makes aggregate initialization as dangerous.
Have I missed something? Is there a context in which the use of uniform initialization is both safe and useful?

I think both problems you addressed have very little to do with uniform initialization itself, but illustrate the dangers of changing an interface.
You could archive the very same suboptimal change in users code by updating your library like this:
struct MyStruct
{
int member1;
int member0;
}
No uniform initialization involed. It was also possible, pre-c++11, to change the constructor chosen by overload resolution:
class some_class
{
public:
some_class(int);
}
User coder:
some_class var(1.0);
If the code were changed to:
class some_class
{
public:
some_class(int);
some_class(double);
}
The second constructor would be called. Again, no uniform initialization involed, yet the same problems occur.
So, whilst both examples do showcase the fact that the meaning of a users code can be changed by changes to a libraries interface, this is not a problem intruduced by or specific to uniform initialization but rather suboptimal design. It merely illustrates the fact that a libraries interface should be designed very carefully.
On the contray, uniform initialization offers some real advantages. For those, see this excellent answer

Related

Why should we initialize data members on declaration (not necessarily on constructor)?

Does anyone could explain me the reason of this coding recommendation ?
Since C++11, please initialize data members on declaration (not
necessary on constructor) :
class Limit
{
public:
Limit() = default;
private:
int32_t quantity = 0;
double price = 0.0;
};
Someone thinks (correctly) that this way the variable is always initialised. Which is a good thing if it is initialised with a meaningful value and bad if the value is not meaningful. For example a person’s year of birth is a number from say 1890 to 2021. Initialising it to 0 isn’t useful and can only prevent the compiler from warning you.
So do this if you have a value that is always a useful initialisation value. I wouldn’t do it for anything that is likely to be overwritten in a constructor or shortly after.
I found this answer from CppCoreGuidelines C-48 :
C.48: Prefer in-class initializers to member initializers in constructors for constant initializers
Reason
Makes it explicit that the same value is expected to be used in all constructors. Avoids repetition. Avoids maintenance problems. It leads to the shortest and most efficient code.
Example, bad
class X { // BAD
int i;
string s;
int j;
public:
X() :i{666}, s{"qqq"} { } // j is uninitialized
X(int ii) :i{ii} {} // s is "" and j is uninitialized
// ...
};
How would a maintainer know whether j was deliberately uninitialized (probably a bad idea anyway) and whether it was intentional to give s the default value "" in one case and qqq in another (almost certainly a bug)? The problem with j (forgetting to initialize a member) often happens when a new member is added to an existing class.
Example
class X2 {
int i {666};
string s {"qqq"};
int j {0};
public:
X2() = default; // all members are initialized to their defaults
X2(int ii) :i{ii} {} // s and j initialized to their defaults
// ...
};
Alternative: We can get part of the benefits from default arguments to constructors, and that is not uncommon in older code. However, that is less explicit, causes more arguments to be passed, and is repetitive when there is more than one constructor:
class X3 { // BAD: inexplicit, argument passing overhead
int i;
string s;
int j;
public:
X3(int ii = 666, const string& ss = "qqq", int jj = 0)
:i{ii}, s{ss}, j{jj} { } // all members are initialized to their defaults
// ...
};
Enforcement
(Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).
(Simple) Default arguments to constructors suggest an in-class initializer might be more appropriate.
There is also the guideline C-45 that explains it.

C++ Check if generic object has member function matching signature

first post, so hopefully not violating any etiquette. Feel free to give suggestions for making the question better.
I've seen a few posts similar to this one: Check if a class has a member function of a given signature, but none do quite what I want. Sure it "works with polymorphism" in the sense that it can properly check subclass types for the function that comes from a superclass, but what I'd like to do is check the object itself and not the class. Using some (slightly tweaked) code from that post:
// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
static_assert(integral_constant<T, false>::value,
"Second template parameter needs to be of function type."
);
};
template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {
template<typename T>
static constexpr auto check(T*) -> typename is_same<
decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;
template<typename>
static constexpr false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};
I'd like to have something like the following:
// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
if (HasFunction<T, int(double)>::value)
cout << "Found it!" << endl;
// Do something with obj.myfunc
else cout << "Nothin to see here" << endl;
}
int main()
{
Y y;
W* w = &y; // same object
DoSomething(y); // Found it!
DoSomething(*w); // Nothin to see here?
}
The problem is that the same object being viewed polymorphically causes different results (because the deduced type is what is being checked and not the object). So for example, if I was iterating over a collection of W*'s and calling DoSomething I would want it to no-op on W's but it should do something for X's and Y's. Is this achievable? I'm still digging into templates so I'm still not quite sure what's possible but it seems like it isn't. Is there a different way of doing it altogether?
Also, slightly less related to that specific problem: Is there a way to make HasFunction more like an interface so I could arbitrarily check for different functions? i.e. not have ".myfunc" concrete within it? (seems like it's only possible with macros?) e.g.
template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
Bar b;
if(HasFoo<b>::value) b.foo();
}
Obviously that's invalid syntax but hopefully it gets the point across.
It's just not possible to perform deep inspection on a base class pointer in order to check for possible member functions on the pointed-to type (for derived types that are not known ahead of time). Even if we get reflection.
The C++ standard provides us no way to perform this kind of inspection, because the kind of run time type information that is guaranteed to be available is very limited, basically relegated to the type_info structure.
Your compiler/platform may provide additional run-time type information that you can hook into, although the exact types and machinery used to provide RTTI are generally undocumented and difficult to examine (This article by Quarkslab attempts to inspect MSVC's RTTI hierarchy)

Casting Parent Struct to Child Struct [duplicate]

In c++ what is object slicing and when does it occur?
"Slicing" is where you assign an object of a derived class to an instance of a base class, thereby losing part of the information - some of it is "sliced" away.
For example,
class A {
int foo;
};
class B : public A {
int bar;
};
So an object of type B has two data members, foo and bar.
Then if you were to write this:
B b;
A a = b;
Then the information in b about member bar is lost in a.
Most answers here fail to explain what the actual problem with slicing is. They only explain the benign cases of slicing, not the treacherous ones. Assume, like the other answers, that you're dealing with two classes A and B, where B derives (publicly) from A.
In this situation, C++ lets you pass an instance of B to A's assignment operator (and also to the copy constructor). This works because an instance of B can be converted to a const A&, which is what assignment operators and copy-constructors expect their arguments to be.
The benign case
B b;
A a = b;
Nothing bad happens there - you asked for an instance of A which is a copy of B, and that's exactly what you get. Sure, a won't contain some of b's members, but how should it? It's an A, after all, not a B, so it hasn't even heard about these members, let alone would be able to store them.
The treacherous case
B b1;
B b2;
A& a_ref = b2;
a_ref = b1;
//b2 now contains a mixture of b1 and b2!
You might think that b2 will be a copy of b1 afterward. But, alas, it's not! If you inspect it, you'll discover that b2 is a Frankensteinian creature, made from some chunks of b1 (the chunks that B inherits from A), and some chunks of b2 (the chunks that only B contains). Ouch!
What happened? Well, C++ by default doesn't treat assignment operators as virtual. Thus, the line a_ref = b1 will call the assignment operator of A, not that of B. This is because, for non-virtual functions, the declared (formally: static) type (which is A&) determines which function is called, as opposed to the actual (formally: dynamic) type (which would be B, since a_ref references an instance of B). Now, A's assignment operator obviously knows only about the members declared in A, so it will copy only those, leaving the members added in B unchanged.
A solution
Assigning only to parts of an object usually makes little sense, yet C++, unfortunately, provides no built-in way to forbid this. You can, however, roll your own. The first step is making the assignment operator virtual. This will guarantee that it's always the actual type's assignment operator which is called, not the declared type's. The second step is to use dynamic_cast to verify that the assigned object has a compatible type. The third step is to do the actual assignment in a (protected!) member assign(), since B's assign() will probably want to use A's assign() to copy A's, members.
class A {
public:
virtual A& operator= (const A& a) {
assign(a);
return *this;
}
protected:
void assign(const A& a) {
// copy members of A from a to this
}
};
class B : public A {
public:
virtual B& operator= (const A& a) {
if (const B* b = dynamic_cast<const B*>(&a))
assign(*b);
else
throw bad_assignment();
return *this;
}
protected:
void assign(const B& b) {
A::assign(b); // Let A's assign() copy members of A from b to this
// copy members of B from b to this
}
};
Note that, for pure convenience, B's operator= covariantly overrides the return type, since it knows that it's returning an instance of B.
If You have a base class A and a derived class B, then You can do the following.
void wantAnA(A myA)
{
// work with myA
}
B derived;
// work with the object "derived"
wantAnA(derived);
Now the method wantAnA needs a copy of derived. However, the object derived cannot be copied completely, as the class B could invent additional member variables which are not in its base class A.
Therefore, to call wantAnA, the compiler will "slice off" all additional members of the derived class. The result might be an object you did not want to create, because
it may be incomplete,
it behaves like an A-object (all special behaviour of the class B is lost).
These are all good answers. I would just like to add an execution example when passing objects by value vs by reference:
#include <iostream>
using namespace std;
// Base class
class A {
public:
A() {}
A(const A& a) {
cout << "'A' copy constructor" << endl;
}
virtual void run() const { cout << "I am an 'A'" << endl; }
};
// Derived class
class B: public A {
public:
B():A() {}
B(const B& a):A(a) {
cout << "'B' copy constructor" << endl;
}
virtual void run() const { cout << "I am a 'B'" << endl; }
};
void g(const A & a) {
a.run();
}
void h(const A a) {
a.run();
}
int main() {
cout << "Call by reference" << endl;
g(B());
cout << endl << "Call by copy" << endl;
h(B());
}
The output is:
Call by reference
I am a 'B'
Call by copy
'A' copy constructor
I am an 'A'
Third match in google for "C++ slicing" gives me this Wikipedia article http://en.wikipedia.org/wiki/Object_slicing and this (heated, but the first few posts define the problem) : http://bytes.com/forum/thread163565.html
So it's when you assign an object of a subclass to the super class. The superclass knows nothing of the additional information in the subclass, and hasn't got room to store it, so the additional information gets "sliced off".
If those links don't give enough info for a "good answer" please edit your question to let us know what more you're looking for.
The slicing problem is serious because it can result in memory corruption, and it is very difficult to guarantee a program does not suffer from it. To design it out of the language, classes that support inheritance should be accessible by reference only (not by value). The D programming language has this property.
Consider class A, and class B derived from A. Memory corruption can happen if the A part has a pointer p, and a B instance that points p to B's additional data. Then, when the additional data gets sliced off, p is pointing to garbage.
In C++, a derived class object can be assigned to a base class object, but the other way is not possible.
class Base { int x, y; };
class Derived : public Base { int z, w; };
int main()
{
Derived d;
Base b = d; // Object Slicing, z and w of d are sliced off
}
Object slicing happens when a derived class object is assigned to a base class object, additional attributes of a derived class object are sliced off to form the base class object.
I see all the answers mention when object slicing happens when data members are sliced. Here I give an example that the methods are not overridden:
class A{
public:
virtual void Say(){
std::cout<<"I am A"<<std::endl;
}
};
class B: public A{
public:
void Say() override{
std::cout<<"I am B"<<std::endl;
}
};
int main(){
B b;
A a1;
A a2=b;
b.Say(); // I am B
a1.Say(); // I am A
a2.Say(); // I am A why???
}
B (object b) is derived from A (object a1 and a2). b and a1, as we expect, call their member function. But from polymorphism viewpoint we don’t expect a2, which is assigned by b, to not be overridden. Basically, a2 only saves A-class part of b and that is object slicing in C++.
To solve this problem, a reference or pointer should be used
A& a2=b;
a2.Say(); // I am B
or
A* a2 = &b;
a2->Say(); // I am B
So ... Why is losing the derived information bad? ... because the author of the derived class may have changed the representation such that slicing off the extra information changes the value being represented by the object. This can happen if the derived class if used to cache a representation that is more efficient for certain operations, but expensive to transform back to the base representation.
Also thought someone should also mention what you should do to avoid slicing...
Get a copy of C++ Coding Standards, 101 rules guidlines, and best practices. Dealing with slicing is #54.
It suggests a somewhat sophisticated pattern to fully deal with the issue: have a protected copy constructor, a protected pure virtual DoClone, and a public Clone with an assert which will tell you if a (further) derived class failed to implement DoClone correctly. (The Clone method makes a proper deep copy of the polymorphic object.)
You can also mark the copy constructor on the base explicit which allows for explicit slicing if it is desired.
The slicing problem in C++ arises from the value semantics of its objects, which remained mostly due to compatibility with C structs. You need to use explicit reference or pointer syntax to achieve "normal" object behavior found in most other languages that do objects, i.e., objects are always passed around by reference.
The short answers is that you slice the object by assigning a derived object to a base object by value, i.e. the remaining object is only a part of the derived object. In order to preserve value semantics, slicing is a reasonable behavior and has its relatively rare uses, which doesn't exist in most other languages. Some people consider it a feature of C++, while many considered it one of the quirks/misfeatures of C++.
1. THE DEFINITION OF SLICING PROBLEM
If D is a derived class of the base class B, then you can assign an object of type Derived to a variable (or parameter) of type Base.
EXAMPLE
class Pet
{
public:
string name;
};
class Dog : public Pet
{
public:
string breed;
};
int main()
{
Dog dog;
Pet pet;
dog.name = "Tommy";
dog.breed = "Kangal Dog";
pet = dog;
cout << pet.breed; //ERROR
Although the above assignment is allowed, the value that is assigned to the variable pet loses its breed field. This is called the slicing problem.
2. HOW TO FIX THE SLICING PROBLEM
To defeat the problem, we use pointers to dynamic variables.
EXAMPLE
Pet *ptrP;
Dog *ptrD;
ptrD = new Dog;
ptrD->name = "Tommy";
ptrD->breed = "Kangal Dog";
ptrP = ptrD;
cout << ((Dog *)ptrP)->breed;
In this case, none of the data members or member functions of the dynamic variable
being pointed to by ptrD (descendant class object) will be lost. In addition, if you need to use functions, the function must be a virtual function.
It seems to me, that slicing isn't so much a problem other than when your own classes and program are poorly architected/designed.
If I pass a subclass object in as a parameter to a method, which takes a parameter of type superclass, I should certainly be aware of that and know the internally, the called method will be working with the superclass (aka baseclass) object only.
It seems to me only the unreasonable expectation that providing a subclass where a baseclass is requested, would somehow result in subclass specific results, would cause slicing to be a problem. Its either poor design in the use of the method or a poor subclass implementation. I'm guessing its usually the result of sacrificing good OOP design in favor of expediency or performance gains.
OK, I'll give it a try after reading many posts explaining object slicing but not how it becomes problematic.
The vicious scenario that can result in memory corruption is the following:
Class provides (accidentally, possibly compiler-generated) assignment on a polymorphic base class.
Client copies and slices an instance of a derived class.
Client calls a virtual member function that accesses the sliced-off state.
Slicing means that the data added by a subclass are discarded when an object of the subclass is passed or returned by value or from a function expecting a base class object.
Explanation:
Consider the following class declaration:
class baseclass
{
...
baseclass & operator =(const baseclass&);
baseclass(const baseclass&);
}
void function( )
{
baseclass obj1=m;
obj1=m;
}
As baseclass copy functions don't know anything about the derived only the base part of the derived is copied. This is commonly referred to as slicing.
class A
{
int x;
};
class B
{
B( ) : x(1), c('a') { }
int x;
char c;
};
int main( )
{
A a;
B b;
a = b; // b.c == 'a' is "sliced" off
return 0;
}
when a derived class object is assigned to a base class object, additional attributes of a derived class object are sliced off (discard) form the base class object.
class Base {
int x;
};
class Derived : public Base {
int z;
};
int main()
{
Derived d;
Base b = d; // Object Slicing, z of d is sliced off
}
When a Derived class Object is assigned to Base class Object, all the members of derived class object is copied to base class object except the members which are not present in the base class. These members are Sliced away by the compiler.
This is called Object Slicing.
Here is an Example:
#include<bits/stdc++.h>
using namespace std;
class Base
{
public:
int a;
int b;
int c;
Base()
{
a=10;
b=20;
c=30;
}
};
class Derived : public Base
{
public:
int d;
int e;
Derived()
{
d=40;
e=50;
}
};
int main()
{
Derived d;
cout<<d.a<<"\n";
cout<<d.b<<"\n";
cout<<d.c<<"\n";
cout<<d.d<<"\n";
cout<<d.e<<"\n";
Base b = d;
cout<<b.a<<"\n";
cout<<b.b<<"\n";
cout<<b.c<<"\n";
cout<<b.d<<"\n";
cout<<b.e<<"\n";
return 0;
}
It will generate:
[Error] 'class Base' has no member named 'd'
[Error] 'class Base' has no member named 'e'
I just ran across the slicing problem and promptly landed here. So let me add my two cents to this.
Let's have an example from "production code" (or something that comes kind of close):
Let's say we have something that dispatches actions. A control center UI for example.
This UI needs to get a list of things that are currently able to be dispatched. So we define a class that contains the dispatch-information. Let's call it Action. So an Action has some member variables. For simplicity we just have 2, being a std::string name and a std::function<void()> f. Then it has an void activate() which just executes the f member.
So the UI gets a std::vector<Action> supplied. Imagine some functions like:
void push_back(Action toAdd);
Now we have established how it looks from the UI's perspective. No problem so far. But some other guy who works on this project suddenly decides that there are specialized actions that need more information in the Action object. For what reason ever. That could also be solved with lambda captures. This example is not taken 1-1 from the code.
So the guy derives from Action to add his own flavour.
He passes an instance of his home-brewed class to the push_back but then the program goes haywire.
So what happened?
As you might have guessed: the object has been sliced.
The extra information from the instance has been lost, and f is now prone to undefined behaviour.
I hope this example brings light about for those people who can't really imagine things when talking about As and Bs being derived in some manner.

Why does initialization of int by parenthesis inside class give error? [duplicate]

For example, I cannot write this:
class A
{
vector<int> v(12, 1);
};
I can only write this:
class A
{
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
};
Why is there a difference between these two declaration syntaxes?
The rationale behind this choice is explicitly mentioned in the related proposal for non static data member initializers :
An issue raised in Kona regarding scope of identifiers:
During discussion in the Core Working Group at the September ’07 meeting in Kona, a question arose about the scope of identifiers in the initializer. Do we want to allow class scope with the possibility of forward lookup; or do we want to require that the initializers be well-defined at the point that they’re parsed?
What’s desired:
The motivation for class-scope lookup is that we’d like to be able to put anything in a non-static data member’s initializer that we could put in a mem-initializer without significantly changing the semantics (modulo direct initialization vs. copy initialization):
int x();
struct S {
int i;
S() : i(x()) {} // currently well-formed, uses S::x()
// ...
static int x();
};
struct T {
int i = x(); // should use T::x(), ::x() would be a surprise
// ...
static int x();
};
Problem 1:
Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:
struct S {
int i(x); // data member with initializer
// ...
static int x;
};
struct T {
int i(x); // member function declaration
// ...
typedef int x;
};
One possible solution is to rely on the existing rule that, if a declaration could be an object or a function, then it’s a function:
struct S {
int i(j); // ill-formed...parsed as a member function,
// type j looked up but not found
// ...
static int j;
};
A similar solution would be to apply another existing rule, currently used only in templates, that if T could be a type or something else, then it’s something else; and we can use “typename” if we really mean a type:
struct S {
int i(x); // unabmiguously a data member
int j(typename y); // unabmiguously a member function
};
Both of those solutions introduce subtleties that are likely to be misunderstood by many users (as evidenced by the many questions on comp.lang.c++ about why “int i();” at block scope doesn’t declare a default-initialized int).
The solution proposed in this paper is to allow only initializers of the “= initializer-clause” and “{ initializer-list }” forms. That solves the ambiguity problem in most cases, for example:
HashingFunction hash_algorithm{"MD5"};
Here, we could not use the = form because HasningFunction’s constructor is explicit.
In especially tricky cases, a type might have to be mentioned twice. Consider:
vector<int> x = 3; // error: the constructor taking an int is explicit
vector<int> x(3); // three elements default-initialized
vector<int> x{3}; // one element with the value 3
In that case, we have to chose between the two alternatives by using the appropriate notation:
vector<int> x = vector<int>(3); // rather than vector<int> x(3);
vector<int> x{3}; // one element with the value 3
Problem 2:
Another issue is that, because we propose no change to the rules for initializing static data members, adding the static keyword could make a well-formed initializer ill-formed:
struct S {
const int i = f(); // well-formed with forward lookup
static const int j = f(); // always ill-formed for statics
// ...
constexpr static int f() { return 0; }
};
Problem 3:
A third issue is that class-scope lookup could turn a compile-time error into a run-time error:
struct S {
int i = j; // ill-formed without forward lookup, undefined behavior with
int j = 3;
};
(Unless caught by the compiler, i might be intialized with the undefined value of j.)
The proposal:
CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup; and that is what this paper proposes, with initializers for non-static data members limited to the “= initializer-clause” and “{ initializer-list }” forms.
We believe:
Problem 1: This problem does not occur as we don’t propose the () notation. The = and {} initializer notations do not suffer from this problem.
Problem 2: adding the static keyword makes a number of differences, this being the least of them.
Problem 3: this is not a new problem, but is the same order-of-initialization problem that already exists with constructor initializers.
One possible reason is that allowing parentheses would lead us back to the most vexing parse in no time. Consider the two types below:
struct foo {};
struct bar
{
bar(foo const&) {}
};
Now, you have a data member of type bar that you want to initialize, so you define it as
struct A
{
bar B(foo());
};
But what you've done above is declare a function named B that returns a bar object by value, and takes a single argument that's a function having the signature foo() (returns a foo and doesn't take any arguments).
Judging by the number and frequency of questions asked on StackOverflow that deal with this issue, this is something most C++ programmers find surprising and unintuitive. Adding the new brace-or-equal-initializer syntax was a chance to avoid this ambiguity and start with a clean slate, which is likely the reason the C++ committee chose to do so.
bar B{foo{}};
bar B = foo();
Both lines above declare an object named B of type bar, as expected.
Aside from the guesswork above, I'd like to point out that you're doing two vastly different things in your example above.
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
The first line initializes v1 to a vector that contains two elements, 12 and 1. The second creates a vector v2 that contains 12 elements, each initialized to 1.
Be careful of this rule - if a type defines a constructor that takes an initializer_list<T>, then that constructor is always considered first when the initializer for the type is a braced-init-list. The other constructors will be considered only if the one taking the initializer_list is not viable.

c++11 unrestricted unions more confused

I start playing with unions and run into trouble by compiling a simple example from a c++11 FAQ. The results are discussed here:
c++11 unrestricted unions example
No I play around with some more code:
Example Code 1:
class A
{
private: int a;
public:
A(): a(0) { cout << "Create A no args" << endl; }
};
class B
{
private: float b;
public:
};
class OneOfN
{
public:
union U
{
A a;
B b;
} u;
};
OneOfN n{}; // Compiles! That I did not expect, but the constructor will not be
// called! But why?
To make the things a bit more strange here comes example 2 with two union members where no one has a default constructor! And the union itself has also no constructor provided but it compiles and works as expected. Wow!
Exmaple 2:
class A
{
private: int a;
public:
A(int _a): a(_a) { cout << "Create A with args" << endl; }
};
class B
{
private: float b;
};
class OneOfN
{
public:
union U
{
A a;
B b;
} u;
};
int main()
{
OneOfN n2{1}; // This compiles as expected, constructor A(int) is called! Fine!
// But we see later, this is not the truth!
};
Question: If the code of example 2 is valid, why there is there no chance to use the given default constructor for a member of a union? Using the constructor with parms looks ok and works as expected. Strange to me!
Continue this mystery and addapt the example to have one more data member in class A we run into trouble. See example 3:
class A
{
private:
int a;
int aa;
public:
A( int _a, int _aa): a(_a), aa(_aa) { cout << "Create with 2 args" << endl; }
};
class B
{
private: float b;
public:
};
class OneOfN
{
public:
union U
{
A a;
B b;
} u;
};
int main()
{
OneOfN n3{2,3}; // Ups! Fails
};
Ups! Now we see that the creation of an instance of OneOfN fails. What happens?
As written in example2, it is not the the constructor A(int) which is called! It is a two step init! First create a A with call to A(int) and then give that object to the copy constructor!
As a result of this, the following change to example 3 makes the example working:
OneOfN n4{A{2,3}}; // Works! Ah! We use implicit the copy construction!
Question:
1) Is this code valid?
2) Why the copy constructor works but default constructors did not? For me as user it looks really strange.
3) Is it true that always, if no default constructor to the union is manually written, the argument to the constructor for the union will passed to the copy constructor of the FIRST union element?
My intention to give this three step example is that you can catch my ideas. As a result I hope this example give a hint for the correct usage of 'unrestricted unions' for other beginners :-) For me the behavior looks very special.
A partial, general answer: things are the way they are because many choices regarding the design of the language were based on engineering trade-offs, rather than on what is theoretically possible.
"These restrictions prevent many subtle errors and simplify the implementation of unions. The latter is important because the use of unions is often an optimization and we won’t want ‘‘hidden costs’’ imposed to compromise that.
The rule that deletes constructors (etc.) from a union with a member that has a constructor (etc.) keeps simple unions simple and forces the programmer to provide complicated operations if they are needed." (The C++ Programming Language, p. 215)
Also,
"When needed, a user can define a class containing a union that properly handles union members with constructors, destructors, and assignments (§8.3.2). If desired, such a class can also prevent the error of writing one member and then reading another.
It is possible to specify an in-class initializer for at most one member. If so, this initializer will be used for default initialization."
And Section 8.3.2 of the aforementioned reference starts with
"To see how we can write a class that overcomes the problems with misuse of a union [...]"
so it might be worth reading.

Resources