【问题标题】:std::array<const T, n> vs std::array<T, n> overload resolutionstd::array<const T, n> vs std::array<T, n> 重载决议
【发布时间】:2018-06-27 02:32:35
【问题描述】:

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

#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&lt;int, 2&gt; 无法自动转换为它的 const 对应项。这让我有些困惑,因为我希望非常量到 const 的转换是“微不足道的”。

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

我的问题是:

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

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

【问题讨论】:

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


    【解决方案1】:

    1) 为什么这里没有自动完成非 const 到 const 的转换?

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

    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

    【讨论】:

    • "Under the hood" 模板仍然会产生 2 个不同的函数(当然可以内联),以便解决方案隐藏问题。仍然是我的 +1,因为它比我所拥有的“更清晰”:)
    • gsl::span 是指南支持库github.com/Microsoft/GSL 中的一个“安全缓冲区” - 由 Bjarn 领导的一项倡议,旨在帮助开发人员最大限度地减少代码中的愚蠢错误并帮助静态代码分析工具,例如一个(现在)集成到 MSVC 中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2018-10-05
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多