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:
could not call the 2 argument constructor. What is happening is that in the expression
(1,2), the1is evaluated before the comma operator, it is discarded, and the result of the expression is2. This obviously calls theinitializer_listconstructor.Enable warnings, e.g. with
-Walland the compiler will tell you about this.Note that the same thing happens in the
vector<int> a{ (1, 2) };call. The1is discarded, and the constructor of vector that takes a single argument is invoked.