【问题标题】:Is value initialization of std::array inside constexpr loop working?constexpr 循环内 std::array 的值初始化是否有效?
【发布时间】:2017-03-06 19:49:45
【问题描述】:

以下代码:

#include<iostream>
#include<array>

using std::size_t;
using std::array;

//#define INIT_BY_HAND 1
#define CONSTEXPR 1

#ifdef CONSTEXPR
constexpr
#endif
size_t accumulator_count()
{
    constexpr size_t nb_rows{2};
    constexpr size_t nb_cols{2};
    size_t nb{0};
    for(size_t k = 0; k < nb_rows; ++k)
    {
        array<size_t,nb_cols> acc{}; // value initialization: expect both elements to be zero
        //for const_cast/static_cast see http://stackoverflow.com/questions/34199774/why-is-non-const-stdarrayoperator-not-constexpr
    #ifdef INIT_BY_HAND
        for(size_t j = 0; j < nb_cols; ++j)
            const_cast<size_t&>(static_cast<array<size_t,nb_cols> const&>(acc)[j]) = 0;
    #endif
        if(k == 0)
            const_cast<size_t&>(static_cast<array<size_t,nb_cols> const&>(acc)[0]) = 1;
        if(k == 1)
            const_cast<size_t&>(static_cast<array<size_t,nb_cols> const&>(acc)[nb_cols-1]) = 1;
        for(size_t j = 0; j < nb_cols; ++j)
            nb += size_t(static_cast<array<size_t,nb_cols> const&>(acc)[j] != 0);
    }
    return nb;
}

int main()
{
#ifdef CONSTEXPR
    constexpr
#endif
    size_t nb{accumulator_count()};
    std::cout << "nb: " << nb << std::endl;
}

在 gcc 5.3.1 (-Wall -std=c++14) 上编译时没有警告,但会产生 错误 输出 3。

如果没有 constexpr(注释掉 #define CONSTEXPR 1 行),它会正确输出 2。

手动初始化(#define INIT_BY_HAND 1 行中的注释)它正确输出 2。

使用 clang 3.8.0 编译,正确输出 2。

问题:这段代码是否符合 c++14 标准或者我错过了什么?

【问题讨论】:

标签: c++ c++14 constexpr


【解决方案1】:

g++ 6.3.0 和 clang++ 3.8.0 都编译并生成值 2。

live example.

这强烈表明 g++ 5.3.1 有错误。

顺便说一句:

namespace notstd {
  template<class T, std::size_t N>
  constexpr T& constexpr_get( std::array<T, N>& arr, std::size_t I ) {
    return const_cast<T&>(const_cast<std::array<T,N> const&>(arr)[I]);
  }
  struct at {
    std::size_t I = 0;
    constexpr at(std::size_t i):I(i){}
    template<class T, std::size_t N>
    friend constexpr T&
    operator->*( std::array<T, N>& arr, at a ) {
      return constexpr_get(arr, a.I);
    }
    // optional
    template<class T, std::size_t N>
    friend constexpr T const&
    operator->*( std::array<T, N> const& arr, at a ) {
      return arr[a.I];
    }
  };
}

using notstd::at 给你一个比所有这些演员更漂亮的中缀方式:

arr->*at(0) = 1;

(谁说我们在 C++ 中还没有扩展方法?)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 2015-10-05
    • 2015-01-02
    • 2012-02-10
    相关资源
    最近更新 更多