![](/img/trans.png)
[英]C++ alternatives to std::array when the size is fixed, but not a constexpr?
[英]Cannot make std::array a constexpr in C++
我在以下代码中收到VS2017的``错误C3615:constexpr函数'to_array'无法导致常量表达式''的编译器错误:
#include <stdio.h>
#include <array>
template <typename T>
static constexpr std::array<std::uint8_t, sizeof(T)> to_array(T value)
{
std::array<std::uint8_t, sizeof(T)> result {};
for (std::size_t i{ sizeof(T) }; i != 0 ; --i)
{
result[i - 1] = static_cast<uint8_t>(value >> ((sizeof(T) - i) * 8));
}
return result;
}
int main()
{
constexpr uint64_t sample = UINT64_C(0xab28ecb46814fe75);
//error C3615: constexpr function 'to_array' cannot result in a constant expression
constexpr auto a = to_array(sample);
return 0;
}
如果理论上std :: array可以是constexpr ,为什么我在这里得到错误?
EDIT1:
它编译时没有循环:
template <typename T>
static constexpr std::array<std::uint8_t, sizeof(T)> to_array(T value)
{
std::array<std::uint8_t, sizeof(T)> result {};
//this is OK
return result;
}
EDIT2:
循环的完整错误消息是:
error C3615: constexpr function 'to_array' cannot result in a constant expression
note: failure was caused by an uninitialized variable declaration
note: see usage of 'result'
如果理论上std :: array可以是constexpr ,为什么我在这里得到错误?
您所提供的链接处理构建 std::array
的一部分constexpr
,没有做别的吧,像你一样。
它编译没有循环
您的错误与循环本身无关,因为它与在constexpr
函数体内的std::array
operator[]
直接使用有关。
自C ++ 17以来 , std::array
operator[]
是constexpr
,但似乎MSVC 19尚未实现它,即使它在规范中。 因此,在您的情况下,启用C ++ 17(编译器标志/std:c++latest
)进行构建将无法直接解决问题:-(
好消息是MSVC 20符合标准 :-)
完整的错误消息是:
error C2131: expression did not evaluate to a constant
note: failure was caused by call of undefined function or one not declared 'constexpr'
note: see usage of 'std::array<uint8_t,8>::operator []'
note: while evaluating 'to_array(12333367839138578037)'
fatal error C1903: unable to recover from previous error(s); stopping compilation
现在,如果我们看一下operator[]
的声明,我们会发现在该版本的Microsoft STD实现中它还不是constexpr
:
reference operator[](_In_range_(0, _Size - 1) size_type _Pos)
解决方法是使用C数组,然后将其转换为std::array
:
template<std::size_t... is, std::size_t n = sizeof...(is)>
constexpr std::array<std::uint8_t, n>
to_array(std::uint8_t (&arr)[n], std::index_sequence<is...>)
{
return {arr[is]...};
}
template <typename T>
constexpr std::array<std::uint8_t, sizeof(T)> to_array(T value)
{
std::uint8_t result[sizeof(T)];
...
return to_array(result, std::make_index_sequence<sizeof(T)>{});
}
要么
template<typename T, std::size_t... is>
constexpr std::array<std::uint8_t, sizeof(T)>
to_array(T value, std::index_sequence<is...>)
{
return {static_cast<std::uint8_t>(value >> ((sizeof(T) - is - 1) * 8))...};
}
template <typename T>
constexpr std::array<std::uint8_t, sizeof(T)> to_array(T value)
{
return to_array(value, std::make_index_sequence<sizeof(T)>{});
}
但是无论如何,您不能在constexpr
上下文中对结果使用operator[]
。
我今天遇到了这个问题。 我决定尝试包装std :: array以查看是否可以添加constexpr支持。 我才刚开始,并且在我使[]运算符重载之前,这种方法确实起作用了。
template <typename T, unsigned S> struct _array : public std::array<T,S> {};
现在可以使用_array代替std :: array。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.