Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

initializer_list, constructors and braced initialization

Tags:

c++

c++11

While reading about different types of initialization, I stumbled upon one of the numerous weird interaction of std::initializer_list (previous post here). It's apparently a simple topic, one of the first presented in C++ books when they present std::vector.

The point is, if you have one constructor that takes a (I guess only) std::initializer_list, when you brace initialize this constructor will be strongly prefered: in other words, std::vector<int> NewVect{5, 10} will create an object containing 5 and 10, not 5 element initialized to 10 (std::vector<int> NewVect(5, 10)).

A special behaviour takes place for auto brace initialization (auto A={1,2,3} will be deduced to be a std::initializer_list<int>). Now, I can't believe in C++ a particular treatment is accorded to specific objects, since to my knowledge header are only well written and useful code snippet. Moreover, those syntaxes don't work if you don't directly or indirectly #include <initializer_list>, even though my compiler, VS2017, prints a very special set of error pointing out that it needs that header to work (you can easily test this out with auto).

So, my question is, given for granted that this behaviour is the effect of code from the initiliazer list's header and my compiler is probably built to assume the use of STD, how is it implemented? Could I reroute this behaviour to never happen aside from explicit call (that is, std::vector<int> NewVect{5, 10} would be equivalent to std::vector<int> NewVect(5, 10) and you would need now to call std::vector<int> NewVect{std::initializer_list<int>{5, 10}})? Would be possible to give this behaviour to other, user-built classes?

like image 583
Andrea Bocco Avatar asked Jan 01 '23 16:01

Andrea Bocco


1 Answers

given for granted that this behaviour is the effect of code from the initiliazer list's header and my compiler is probably built to assume the use of STD, how is it implemented?

There is a special rule in the Standard that says something along the lines of: "if you are using list-initialization ({...}) to construct an object, and the object has a constructor that takes std::initializer_list, that constructor is chosen regardless of overload resolution". This means that std::initializer_list constructors always have priority over others when using {...} initialization syntax.


Could I reroute this behaviour to never happen aside from explicit call

In your classes, you can avoid using std::initializer_list. Then this behavior will never occur. You cannot change this for std:: classes.


Would be possible to give this behaviour to other, user-built classes?

Not with your desired syntax, as std::initializer_list is special. You can create your own initializer_list alternative, or use something like a variadic template constructor to force users to have an explicit syntax.

like image 102
Vittorio Romeo Avatar answered Jan 13 '23 07:01

Vittorio Romeo