I am recently having a problem with uniform initialization on C++14 standard. I wrote a code which declares a class having two constructors, first one is parameterized constructor and the other one is a constructor having intializer_list
. The code looks as follows,
#include <iostream>
#include <vector>
class MyClass final {
public:
MyClass() = default;
explicit MyClass(const int a, const int b)
: m_a(a)
, m_b(b)
{
std::cout << "From constructor" << std::endl;
};
MyClass(std::initializer_list<int> init_li)
: m_a(init_li[0])
, m_b(init_li[1])
{
std::cout << "Initializer List constructor" << std::endl;
}
void PrintValues() const
{
std::cout << m_a << " " << m_b << std::endl;
}
private:
int m_a, m_b;
}
int
main(void)
{
using namespace std;
vector<int> a{ 1, 2 }; // Creates a vector with initializer list. Very nice.
vector<int> a{ (1, 2) }; // Calls a vector constructor "explicit vector(std::size_t __n, const std::allocator<int> &__a = std::vector<int>::allocator_type())" NOT INITIALIZER LIST constructor. Okay.
MyClass a{ 1, 2 }; // Calls the initializer list constructor. Fine.
MyClass b{ (1, 2) }; // Also calls the initializer list constructor. What???
b.PrintValues();
return 0;
}
So, my question is why can't I call a constructor other than initializer list with uniform initialization in MyClass just like I did in vector with parentheses?
This code:
MyClass a2{ (1, 2) };
could not call the 2 argument constructor. What is happening is that in the expression (1,2)
, the 1
is evaluated before the comma operator, it is discarded, and the result of the expression is 2
. This obviously calls the initializer_list
constructor.
Enable warnings, e.g. with -Wall
and the compiler will tell you about this.
Note that the same thing happens in the vector<int> a{ (1, 2) };
call. The 1
is discarded, and the constructor of vector that takes a single argument is invoked.