What determines which constructor should be used when initializing objects using this syntax; is it compiler dependent? (Using VS2015):
Vector v { 3 };
I'm creating my own Vector class (learning C++11) and I have the following:
class Vector
{
public:
Vector(initializer_list<double> lst);
Vector(int s);
// ...
private:
double* elem;
int sz;
};
and:
int main()
{
Vector v1 { 3 }; //calls init_list ctor
Vector v2 { static_cast<int>(3)}; //calls init_list ctor
Vector v3 = 3; //call int ctor
}
My initial thought was using the { 3 } syntax would call the constructor that accepts an int, then realized that it makes sense since I could also use something like { 3, 4, 5, 6 } and that would work--the array passed would been seen as doubles and a Vector would be instantiated.
Then I thought, "how can I use the {}-notation and call the constructor that accepts an int? " I tried casting it to an int so that it would force use of said constructor but that didn't happen. That's when I found out I can use the method used to init v3.
I played around a little bit more and removed the constructor with the initializer_list<double> argument, and to my surprise, initializing v1 and v2 was calling the constructor that takes an int for an argument.
So, is this normal/standard? Is it considered a feature? I would think the int constructor would have precedence when passing a single int to the initializer vs. an implicit cast to double and double*.
This is standard. If there is a std::initializer_list constructor with compatible arguments, that will be chosen over a different constructor if list-initialization is used.
Vector v3 = 3;
That is valid because you have a non-explicit constructor taking an int, so implicit conversions from int to Vector are allowed. That's generally not such a good idea as you can get implicit conversions when you don't want them.
The way to call a non-initializer-list constructor when an initializer-list constructor exists is to use parentheses for the initialization:
Vector v1 (3); //int constructor
Vector v2 {3}; //initializer_list constructor
Generally its best to avoid these logically ambiguous constructors if you can help it, as these rules can be annoying. In this case, since you are emulating std::vector, its probably okay.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With