std :: array <const t,=“” n =“”>与std :: array <t,n =“”>重载解析

时间:2018-06-27 02:32:36

标签: c++ arrays templates c++14 c++17

这个问题似乎很简单,但我只能以“丑陋”的方式解决。这是一个简短的代码:

#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::arrayint转换失败。

注释掉第一个构造函数会给出一个明确的编译器错误,即std::array<int, 2>无法自动转换为它的const对应对象。这让我有些困惑,因为我希望从非const到const的转换是“琐碎的”。

通过引入第三个构造函数(在代码示例中对此进行了注释)解决了该问题,但这看起来有些矫kill过正。

我的问题是:

  1. 为什么非const到const的转换在这里不是自动完成的?
  2. 是否可以在不引入构造函数的第三个非常量版本的情况下对其进行“修复”?
  3. 更改构造函数以接受gsl::span而不是std::array也有帮助,但同时也感觉像是过大了

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

1 个答案:

答案 0 :(得分:3)

  

1)为什么这里不自动完成从非常量到常量的转换?

因为std::array<T, Dim> conststd::array<T const, Dim>是不同的类型,而我的c ++++则说:“未知从'array<int, [...]>'到'array<const int, [...]>'的转换”

  

2)是否可以在不引入构造函数的第三个非const版本的情况下对其进行“修复”?

关于模板构造函数

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 = enter image description here;
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