统一初始化调用构造函数而不是初始化列表

Uniform Initialization to call a constructor other than initializer list

我最近遇到了 C++14 标准统一初始化的问题。我写了一个代码,它声明一个 class 有两个构造函数,第一个是参数化构造函数,另一个是具有 intializer_list 的构造函数。代码如下所示,

#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;
}

所以,我的问题是,为什么我不能像在带括号的向量中那样在 MyClass 中调用具有统一初始化的初始化列表以外的构造函数?

此代码:

MyClass a2{ (1, 2) };

无法调用 2 参数构造函数。发生的事情是,在表达式 (1,2) 中,1 在逗号运算符之前计算,它被丢弃,表达式的结果是 2。这显然调用了 initializer_list 构造函数。

启用警告,例如使用 -Wall 编译器会告诉你这个。


请注意,同样的事情发生在 vector<int> a{ (1, 2) }; 调用中。 1 被丢弃,调用带有单个参数的 vector 的构造函数。