当前位置:  开发笔记 > 编程语言 > 正文

为什么非const std :: array :: operator []不是constexpr?

如何解决《为什么非conststd::array::operator[]不是constexpr?》经验,为你挑选了3个好方法。

我正在尝试使用给定的函数在编译时填充2D数组.这是我的代码:

template
struct Table
{
  int data[H][W];
  //std::array, W> data;  // This does not work

  constexpr Table() : data{}
  {
    for (int i = 0; i < H; ++i)
      for (int j = 0; j < W; ++j)
        data[i][j] = i * 10 + j;  // This does not work with std::array
  }
};

constexpr Table<3, 5> table;  // I have table.data properly populated at compile time

它运行得很好,table.data在编译时正确填充.

然而,如果我改变普通2D阵列int[H][W]std::array, W>我有在循环体中的错误:

error: call to non-constexpr function 'std::array<_Tp, _Nm>::value_type& std::array<_Tp, _Nm>::operator[](std::array<_Tp, _Nm>::size_type) [with _Tp = int; long unsigned int _Nm = 3ul; std::array<_Tp, _Nm>::reference = int&; std::array<_Tp, _Nm>::value_type = int; std::array<_Tp, _Nm>::size_type = long unsigned int]'
data[i][j] = i * 10 + j;
^
Compilation failed

显然,我试图调用非常量重载std::array::operator[],而不是constexpr.问题是,为什么不constexpr呢?如果C++ 14允许我们修改在constexpr范围内声明的变量,为什么不支持std::array

我曾经认为这std::array就像普通阵列一样,只是更好.但这是一个例子,我可以使用普通数组,但不能使用std::array.



1> Mikhail..:

好吧,这确实是标准的疏忽.甚至还存在一个解决这个问题的建议:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0107r0.pdf

[N3598]删除了constexpr成员函数的隐式标记为const.但是,在这次更改之后没有重新访问std :: array的成员函数,导致在std :: array的接口中对constexpr的支持出人意料.本文通过将constexpr添加到std :: array的成员函数来修复这个遗漏,该函数可以用最少量的工作来支持它.



2> 101010..:

std::array::operator[]因为C++ 14是constexpr但也是const合格:

constexpr const_reference operator[]( size_type pos ) const;
                                                      ^^^^^

因此,您必须强制转换数组以调用正确的operator[]重载:

template
struct Table
{
  //int data[H][W];
  std::array, W> data;  // This does not work

  constexpr Table() : data{} {
    for (int i = 0; i < W; ++i)
      for (int j = 0; j < H; ++j)
        const_cast(static_cast const&>(static_cast, W> const&>(data)[i])[j]) = 10 + j;
  }
};

现场演示

编辑:

与某些人相反,const_cast以这种方式使用并不意味着未定义的行为.事实上,正如在放宽提议中所提出的constexpr那样,用户需要进行这项工作const_cast,以便至少在C++ 17中解决问题之前唤起正确的下标操作符重载(参见链接).



3> Richard Hodg..:

虽然我的第一个想法是"为什么你需要在非const数组上使用constexpr方法"?...

然后我坐下来写了一个小测试,看看这个想法是否有意义:

#include 

using namespace std;
struct X{

    constexpr X()
    : _p { 0, 1, 2, 3, 4, 5, 6, 7, 9 }
    {
    }

    constexpr int& operator[](size_t i)
    {
        return _p[i];
    }

    int _p[10];
};

constexpr int foo()
{
    X x;
    x[3] = 4;
    return x[3];
}


auto main() -> int
{
    cout << foo() << endl;

    return 0;
}

事实证明它确实如此.

因此,我得出的结论是,委员会采取了与我所做的相同的"明显"观点,并对这一想法不屑一顾.

在我看来好像可以向委员会提交一份提案,以便在c ++ 17中对其进行更改 - 以此问题为例.

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有