这个问题看起来很简单,但我只能用“丑陋”的方式解决它。这是一个简短的代码:
#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 的转换是“微不足道的”。
通过引入第三个构造函数(在代码示例中注释掉)解决了这个问题,但这看起来有点矫枉过正。
我的问题是:
- 为什么这里没有自动完成非常量到常量的转换?
- 是否可以在不引入构造函数的第三个非常量版本的情况下“修复”这个问题?
- 更改构造函数以接受
gsl::span
而不是std::array
也有帮助,但也感觉有点矫枉过正
我正在使用 C++17 设置在 MSVC 2017 15.7.4 上进行编译。
最佳答案
1) Why is the non-const to const conversion not done automatically here?
因为 std::array<T, Dim> const
和 std::array<T const, Dim>
是不同的类型,我的 clang++ 怎么说,“没有已知的从‘array<int, [...]>
’到‘array<const int, [...]>
’的转换”
2) Can this be "fixed" without introducing the third, non-const version of the constructor?
模板构造器呢
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 = {{0}};
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) Changing the constructor to accept gsl::span instead of std::array also helps, yet also feels like an overkill as well
抱歉,我不明白第三个问题(?)(我也不知道 gls::span
)
关于c++ - std::array<const T, n> 与 std::array<T, n> 重载解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51053742/