代码之家  ›  专栏  ›  技术社区  ›  Franko Leon Tokalić

不明确的构造函数调用(我假设)

  •  1
  • Franko Leon Tokalić  · 技术社区  · 10 年前

    我有一个矩阵类的定义如下:

    template <typename T, unsigned int N, unsigned int M>
    class TMatrixNxM //Rows x columns
    {
    public:
        TMatrixNxM(T = T(0)); //Default constructor
        TMatrixNxM(const std::array<std::array<T, M>, N>&); //Construct from array
        TMatrixNxM(std::initializer_list<std::initializer_list<T>>); //Initializer
    
        //...
    private:
        std::array<std::array<T, M>, N> data; //ROW-MAJOR
    };
    

    现在,在使用矩阵的代码中,我有:

    Math::Matrix3x3 b({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
    

    (注: 矩阵x3x3 是的typedef TMatrixNxM<浮动,3,3> 而且,它位于 数学 命名空间)

    直到现在,它仍然有效,因为我并不总是有那个数组构造函数,只有初始化器列表1。但是现在,编译器甚至没有完成编译 碰撞 ! (我收到“停止工作”弹出窗口,我必须关闭它,我正在使用MS VS Express 2013)

    如果我这样做:

    Math::Matrix3x3 b = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    

    然后它工作得很好。这就是我 假定 :

    当我这样做时,就不会有歧义,因为你只能调用 初始化程序列表 构造函数。对于第一种方法,编译器可能会感到困惑,因为 大堆 是一种聚合类型,这意味着初始化以双大括号开始,例如:{{…}},但由于我有一个初始值设定项列表,我必须使用双大括号。但这真的应该是一个问题吗,因为我从来没有做过双大括号,这些都是单大括号列表中的单大括号的列表吗?

    这里到底发生了什么,我该如何解决这个问题?

    感谢您抽出时间!

    编辑

    如果我让构造函数通过常量指针获取数组,编译器就不会崩溃了(因为我永远不会直接在构造函数调用中扑通数组,所以我有初始化器列表):

    TMatrixNxM(const std::array<std::array<T, M>, N>*);
    

    然而,有人能解释之前的实际问题吗?我的假设是正确的吗?

    这里有一个最小的可编译(或者,好吧,不是)代码,可以用来测试:

    #include <array>
    #include <initializer_list>
    
    template <typename T, unsigned int N, unsigned int M>
    class TMatrixNxM //Rows x columns
    {
    public:
        TMatrixNxM(T = T(0));
        TMatrixNxM(const std::array<std::array<T, M>, N>&);
        TMatrixNxM(std::initializer_list<std::initializer_list<T>>);
    private:
        std::array<std::array<T, M>, N> data; //ROW-MAJOR
    };
    
    template <typename T, unsigned int N, unsigned int M>
    TMatrixNxM<T, N, M>::TMatrixNxM(T par_value)
    {
        std::array<T, M> temp;
        temp.fill(par_value);
        data.fill(temp);
    }
    
    
    template <typename T, unsigned int N, unsigned int M>
    TMatrixNxM<T, N, M>::TMatrixNxM(const std::array<std::array<T, M>, N> &par_values)
    {
        data = par_values;
    }
    
    
    template <typename T, unsigned int N, unsigned int M>
    TMatrixNxM<T, N, M>::TMatrixNxM(std::initializer_list<std::initializer_list<T>> par_values)
    {
        int i = 0;
    
        for(std::initializer_list<T> row : par_values)
        {
            int j = 0;
    
            for(T value : row)
            {
                data[i][j] = value;
                ++j;
            }
    
            ++i;
        }
    }
    
    int main()
    {
        TMatrixNxM<float, 3, 3> b({{1, 2, 3}, {4, 5, 6}, {7, 8, 9}});
    
        return 0;
    }
    

    如果用数组注释掉构造函数声明/定义,那么它应该可以很好地编译和执行。如前所述,我使用的是MS VS Express 2013的编译器。

    1 回复  |  直到 10 年前
        1
  •  0
  •   Franko Leon Tokalić    10 年前

    看起来它在微软的编译器上不起作用。我尝试在使用GCC的Linux机器上编译相同的代码,并且编译时没有问题。而且它确实在按应有的方式调用初始值设定项列表构造函数。如果我在变量中创建一个数组并传递它,它也会很好地编译,并调用数组构造函数:

    std::array<float, 3> a = {{1, 2, 3}};
    std::array<std::array<float, 3>, 3> b = {{a, a, a}};
    
    TMatrixNxM<float, 3, 3> mat(b);
    

    如果我直接初始化数组,它还会编译并调用数组构造函数:

    TMatrixNxM<float, 3, 3> mat({{ {{1, 2, 3}}, {{4, 5, 6}}, {{7, 8, 9}}  }});