不明确的构造函数调用(我假设)
Ambiguous constructor call (I assume)
我有一个矩阵 class 定义如下:
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}});
(注:Matrix3x3 是 TMatrixNxM< float, 3, 3> 的类型定义,而且,它在 数学命名空间)
直到现在,它都有效,因为我并不总是有那个数组构造函数,只有初始化列表之一。可是现在,编译器还没编译完,就崩溃! (我收到 "stopped working" 弹出窗口,我必须关闭它,我使用的是 MS VS Express 2013)
如果我这样做:
Math::Matrix3x3 b = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
然后它工作正常。这就是我假设:
当我那样做时,就没有歧义,因为您只能那样调用 initializer_list 构造函数。对于第一种方法,编译器可能会感到困惑,因为 array 是一种聚合类型,这意味着初始化以双括号开始,例如:{{...}},但也因为我有一个initializer list of initializer lists 我必须使用双括号。但这真的是个问题吗,因为我从来没有真正做过双大括号,那些是更大的单大括号列表中的单大括号列表?
这里到底发生了什么,我该如何解决这个问题?
感谢您的宝贵时间!
编辑
如果我让构造函数通过 const 指针获取数组,编译器不会再崩溃(因为我永远不会真正在构造函数调用中直接 plop 数组,我有初始化列表):
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;
}
如果您用数组注释掉构造函数 declaration/definition 那么它应该可以正常编译和执行。如前所述,我使用的是 MS VS Express 2013 的编译器。
嗯,看起来它在 Microsoft 的编译器上不起作用。我尝试在使用 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}} }});
我有一个矩阵 class 定义如下:
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}});
(注:Matrix3x3 是 TMatrixNxM< float, 3, 3> 的类型定义,而且,它在 数学命名空间)
直到现在,它都有效,因为我并不总是有那个数组构造函数,只有初始化列表之一。可是现在,编译器还没编译完,就崩溃! (我收到 "stopped working" 弹出窗口,我必须关闭它,我使用的是 MS VS Express 2013)
如果我这样做:
Math::Matrix3x3 b = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
然后它工作正常。这就是我假设:
当我那样做时,就没有歧义,因为您只能那样调用 initializer_list 构造函数。对于第一种方法,编译器可能会感到困惑,因为 array 是一种聚合类型,这意味着初始化以双括号开始,例如:{{...}},但也因为我有一个initializer list of initializer lists 我必须使用双括号。但这真的是个问题吗,因为我从来没有真正做过双大括号,那些是更大的单大括号列表中的单大括号列表?
这里到底发生了什么,我该如何解决这个问题?
感谢您的宝贵时间!
编辑
如果我让构造函数通过 const 指针获取数组,编译器不会再崩溃(因为我永远不会真正在构造函数调用中直接 plop 数组,我有初始化列表):
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;
}
如果您用数组注释掉构造函数 declaration/definition 那么它应该可以正常编译和执行。如前所述,我使用的是 MS VS Express 2013 的编译器。
嗯,看起来它在 Microsoft 的编译器上不起作用。我尝试在使用 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}} }});