数组初始值设定项的构造函数歧义
Constructor ambiguity with array initializer
我有一个问题,在使用 VS2017(C++14、C++17 和 ISO 最新版本)时,我无法将某个构造函数与数组初始值设定项一起使用。
我收到一个 C2397 conversion from 'double' to 'unsigned int' requires a narrowing conversion
错误,当它应该使用填充有单个元素的容器调用构造函数时。
#include <vector>
class obj
{
public:
obj(const std::vector<double>& values, unsigned int stride)
: values_(values), stride_(stride)
{
}
obj(unsigned int m, unsigned int n)
: stride_(n)
{
}
private:
unsigned int stride_;
std::vector<double> values_;
};
int main(int argc, char** argv)
{
obj m(1, 1); // correct constructor called.
obj mm({ 42.0 }, 1); // Error C2397
return 0;
}
我可以通过显式声明容器来解决这个问题...
obj mm(std::vector<double>({ 42.0 }), 1);
或者用多个项目初始化容器...
obj mm({ 42.0, 12.0 }, 1);
后者显然没有用,而前者有点烦人,因为它是包含单个项目的容器的极端情况(尽管不是世界末日)。我认为这可能只对双打有问题(没有文字声明),但它甚至在用文字初始化浮点数时也会发生。即容器是 std::vector<float>
,以下行仍然错误 C2397。
obj mm({ 42.0f }, 1);
我不相信编译器错误我自己没有遇到过很多(尽管它们显然存在),但我不禁认为这可能是一个,或者如果不是,是否有任何提及标准如何处理这种情况。理想情况下,我希望能够在不显式声明容器类型的情况下使用数组初始值设定项,因为当容器中存在多个项目时我可以这样做。这可能吗?
使用 {{
和 }}
是所有情况下的解决方法
obj mm({{ 42.0 }}, 1);
和
obj mm({{ 42.0, 12.0 }}, 1);
虽然第二种情况当然没有歧义(使用单大括号是在利用大括号省略)。
这个问题很好地介绍了主题:Brace elision in std::array initialization
你的意思是下面的吗
obj mm({ 1, 42.0 }, 1);
或以下
obj mm({ { 42.0 } }, 1);
可以向对象添加具有 std::initializer_list
的构造函数。
样本:
#include <iostream>
#include <vector>
struct Obj {
std::vector<double> values;
unsigned stride;
Obj(std::initializer_list<double> values, unsigned stride = 1):
values(values), stride(stride)
{
std::cout << "Obj::Obj(std::initializer_list<double>, unsigned)\n";
}
Obj(const std::vector<double> &values, unsigned stride = 1):
values(values), stride(stride)
{
std::cout << "Obj::Obj(const std::vector<double>&, unsigned)\n";
}
Obj(unsigned m, unsigned stride = 1):
stride(stride)
{
std::cout << "Obj::Obj(unsigned, unsigned)\n";
}
};
int main()
{
Obj mm({ 42.0f }, 1);
Obj mm1(1, 1);
Obj mm2(std::vector<double>({ 42.0 }), 1);
Obj mm3({ 42.0, 12.0 }, 1);
Obj mm4(std::vector<double>{ 42.0 }, 1);
}
输出:
Obj::Obj(std::initializer_list<double>, unsigned)
Obj::Obj(unsigned, unsigned)
Obj::Obj(const std::vector<double>&, unsigned)
Obj::Obj(std::initializer_list<double>, unsigned)
Obj::Obj(const std::vector<double>&, unsigned)
我有一个问题,在使用 VS2017(C++14、C++17 和 ISO 最新版本)时,我无法将某个构造函数与数组初始值设定项一起使用。
我收到一个 C2397 conversion from 'double' to 'unsigned int' requires a narrowing conversion
错误,当它应该使用填充有单个元素的容器调用构造函数时。
#include <vector>
class obj
{
public:
obj(const std::vector<double>& values, unsigned int stride)
: values_(values), stride_(stride)
{
}
obj(unsigned int m, unsigned int n)
: stride_(n)
{
}
private:
unsigned int stride_;
std::vector<double> values_;
};
int main(int argc, char** argv)
{
obj m(1, 1); // correct constructor called.
obj mm({ 42.0 }, 1); // Error C2397
return 0;
}
我可以通过显式声明容器来解决这个问题...
obj mm(std::vector<double>({ 42.0 }), 1);
或者用多个项目初始化容器...
obj mm({ 42.0, 12.0 }, 1);
后者显然没有用,而前者有点烦人,因为它是包含单个项目的容器的极端情况(尽管不是世界末日)。我认为这可能只对双打有问题(没有文字声明),但它甚至在用文字初始化浮点数时也会发生。即容器是 std::vector<float>
,以下行仍然错误 C2397。
obj mm({ 42.0f }, 1);
我不相信编译器错误我自己没有遇到过很多(尽管它们显然存在),但我不禁认为这可能是一个,或者如果不是,是否有任何提及标准如何处理这种情况。理想情况下,我希望能够在不显式声明容器类型的情况下使用数组初始值设定项,因为当容器中存在多个项目时我可以这样做。这可能吗?
使用 {{
和 }}
是所有情况下的解决方法
obj mm({{ 42.0 }}, 1);
和
obj mm({{ 42.0, 12.0 }}, 1);
虽然第二种情况当然没有歧义(使用单大括号是在利用大括号省略)。
这个问题很好地介绍了主题:Brace elision in std::array initialization
你的意思是下面的吗
obj mm({ 1, 42.0 }, 1);
或以下
obj mm({ { 42.0 } }, 1);
可以向对象添加具有 std::initializer_list
的构造函数。
样本:
#include <iostream>
#include <vector>
struct Obj {
std::vector<double> values;
unsigned stride;
Obj(std::initializer_list<double> values, unsigned stride = 1):
values(values), stride(stride)
{
std::cout << "Obj::Obj(std::initializer_list<double>, unsigned)\n";
}
Obj(const std::vector<double> &values, unsigned stride = 1):
values(values), stride(stride)
{
std::cout << "Obj::Obj(const std::vector<double>&, unsigned)\n";
}
Obj(unsigned m, unsigned stride = 1):
stride(stride)
{
std::cout << "Obj::Obj(unsigned, unsigned)\n";
}
};
int main()
{
Obj mm({ 42.0f }, 1);
Obj mm1(1, 1);
Obj mm2(std::vector<double>({ 42.0 }), 1);
Obj mm3({ 42.0, 12.0 }, 1);
Obj mm4(std::vector<double>{ 42.0 }, 1);
}
输出:
Obj::Obj(std::initializer_list<double>, unsigned)
Obj::Obj(unsigned, unsigned)
Obj::Obj(const std::vector<double>&, unsigned)
Obj::Obj(std::initializer_list<double>, unsigned)
Obj::Obj(const std::vector<double>&, unsigned)