std::array<const T, n> vs std::array<T, n> 过载分辨率

std::array<const T, n> vs std::array<T, n> overload resolution

本文关键字:std gt array lt 分辨率 vs const      更新时间:2023-10-16

这个问题看起来很简单,但我只能用"丑陋"的方式解决它。下面是一个简短的代码:

#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 对应项。这对我来说有点令人费解,因为我希望非常量到常量转换是"微不足道的"。

通过引入第三个构造函数(在代码示例中注释掉(解决了该问题,但这看起来有点矫枉过正。

我的问题是:

  1. 为什么非常量到常量转换在这里没有自动完成?
  2. 是否可以在不引入构造函数的第三个非常量版本的情况下"修复"此问题?
  3. 更改构造函数以接受gsl::span而不是std::array也有帮助,但也感觉有点矫枉过正

我正在使用 C++17 设置在 MSVC 2017 15.7.4 上进行编译。

1( 为什么这里的非常量到常量转换没有自动完成?

因为std::array<T, Dim> conststd::array<T const, Dim>是不同的类型,而且,我的clang++怎么说,"没有已知的从'array<int, [...]>'到'array<const int, [...]>'的转换">

2(是否可以在不引入构造函数的第三个非常量版本的情况下"修复"此问题?

模板构造函数呢

template <typename T>
A (std::array<T, 2> const &) {}

T在哪里可以同时匹配intint const

如果你想强加T只是intint 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(将构造函数更改为接受gsl::span而不是std::array也有帮助,但也感觉有点矫枉过正

对不起,我不明白第三个问题(?((我不知道gls::span(