这个问题似乎很简单,但我只能以“丑陋”的方式解决。这是一个简短的代码:
#include <array>
struct A {
A(int , int = 0) {}
A(std::array<const int, 2>) {}
//A(std::array<int, 2>) {}
};
int main(){
std::array<int, 2> a = {0};
const A x(a);
return 0;
}
按原样,编译器正在尝试使用A(int, int = 0)
构造函数,并且当然会导致std::array
到int
转换失败。
注释掉第一个构造函数会给出一个明确的编译器错误,即std::array<int, 2>
无法自动转换为它的const对应对象。这让我有些困惑,因为我希望从非const到const的转换是“琐碎的”。
通过引入第三个构造函数(在代码示例中对此进行了注释)解决了该问题,但这看起来有些矫kill过正。
我的问题是:
gsl::span
而不是std::array
也有帮助,但同时也感觉像是过大了我正在使用C ++ 17设置在MSVC 2017 15.7.4上进行编译。
答案 0 :(得分:3)
1)为什么这里不自动完成从非常量到常量的转换?
因为std::array<T, Dim> const
和std::array<T const, Dim>
是不同的类型,而我的c ++++则说:“未知从'array<int, [...]>
'到'array<const int, [...]>
'的转换”
2)是否可以在不引入构造函数的第三个非const版本的情况下对其进行“修复”?
关于模板构造函数
template <typename T>
A (std::array<T, 2> const &) {}
T
可以同时匹配int
和int const
吗?
如果您想强加T
仅是int
或int const
(例如,不是long const
),则可以通过SFINAE进行以下操作>
template <typename T>
A (std::array<T, 2>,
std::enable_if_t<std::is_same<T const, int const>{}> * = nullptr)
{ }
所以你可以拥有
std::array<int, 2> a = ;
std::array<int const, 2> b = {{0}};
std::array<long const, 2> c = {{0}};
const A x(a); // compile
const A y(b); // compile
const A z(c); // compilation error
3)更改构造函数以接受gsl :: span而不是std :: array也有帮助,但同时也感觉像是过大了
对不起,但我不明白第三个问题(?)(而且我不知道gls::span
)