C++ 如何在编译时使用std::make_tuple?

C++ 如何在编译时使用std::make_tuple?,c++,c++14,c++17,std,constexpr,C++,C++14,C++17,Std,Constexpr,由于使用std::make_tuple,返回std::array的constepr函数在编译时不起作用。有没有办法克服这个问题 当我试图删除constexpr规范时。它工作正常。然而,我们项目的目标是在编译时提供这种功能评估 我得到了以下错误: 在呼叫部分: error: call to non-constexpr function ‘std::tuple<_Elements>& std::tuple<_Elements>::operator=(std::tupl

由于使用std::make_tuple,返回
std::array
的constepr函数在编译时不起作用。有没有办法克服这个问题

当我试图删除constexpr规范时。它工作正常。然而,我们项目的目标是在编译时提供这种功能评估

我得到了以下错误:

在呼叫部分:

error: call to non-constexpr function ‘std::tuple<_Elements>& std::tuple<_Elements>::operator=(std::tuple<_Elements>&&) [with _Elements = {unsigned int, unsigned int, unsigned int}]’
错误:调用非constexpr函数“std::tuple&std::tuple::operator=(std::tuple&)[with _Elements={unsigned int,unsigned int,unsigned int}”
在功能部分:

error: ‘constexpr std::array<std::tuple<unsigned int, unsigned int, unsigned int>, SIZE> GenArrayTuple() [with long unsigned int SIZE = 128]’ called in a constant expression
错误:在常量表达式中调用了:“constexpr std::array GenArrayTuple()[with long unsigned int SIZE=128]”
代码如下

template<std::size_t SIZE>
constexpr std::array<std::tuple<uint32_t, uint32_t, uint32_t>, SIZE> 
GenArrayTuple() {
  std::array<std::tuple<uint32_t, uint32_t, uint32_t>, SIZE> array;
  for (uint32_t i = 0; i < SIZE; ++i) {
    // FIXME constexpr
    arr[2*i] = std::make_tuple(i, i * 2, i * 3 + 1);
  }
  return array;
}

constexpr uint32_t n = 128; 
constexpr auto array_tuple = GenArrayTuple<n>();
模板
constexpr std::数组
GenArrayTuple(){
std::数组;
对于(uint32_t i=0;i
在C++14或更高版本中使用常量表达式实际上没有问题,因为C++14将其更改为
constexpr
。因此,它是一个有效的常量表达式,只要用于初始化元组元素的任何类构造函数都作为有效的常量表达式进行计算(并且当元素类型都是标量(如
std::uint32\t
)时,就没有此类构造函数)

但是请仔细查看错误消息。它抱怨的函数是(去掉一些细节)
tuple&tuple::operator=(tuple&&)
。在当前C++版本中,<>代码> STD::tuple < /C> >未标记为“代码> CONTXPRP</CUT>”,这意味着“<代码> tuple < /Cord>对象的任何赋值不是有效常量表达式”。(CPPaseCy.com指出,它们将在C++ 20中被标记为代码> CONTXPRPR <代码>;这通常反映了已经由适当C++工作组接受的建议的变化)

因此,要解决这个问题,您需要一次性初始化
数组
,而不是在循环中分配其元素。可能最简单的方法是借助以下工具:

#包括
#包括
#包括
#包括
模板
constexpr std::数组
GenArrayTuple\u助手(std::integer\u序列){
返回{std::make_tuple(I,I*2,I*3+1)…};
}
模板
constexpr std::数组
GenArrayTuple(){
返回GenArrayTuple\u helper(std::make\u integer\u sequence{});
}

std::make_tuple
是自C++14以来的
constepr
。您的编译器是否完全支持C++14,您是否在C++14或更高的模式下运行?错误消息不是关于
make\u tuple
,而是关于
operator=
,实际上在C++14或C++17中不是
constexpr
。(但它是在最新的C++20草稿中。)@ShadowRanger你好!谢谢你的回复。我在GCC 7.2.0中使用c++17。@aschepler我不知道当前的c++1x版本不支持赋值
operator=
。谢谢你的洞察力。那么,您的意思是我们不能在编译时分配数组元素?@user9414424:问题在于
tuple
操作符=
,因此,
array
s可以在编译时分配它们的元素,只要所讨论的元素类型有一个
constepr
操作符=
,就是这样。谢谢您的回答!顺便问一下,
I
是保留字符吗??我收到了一条错误消息
error:expected'>'before'('token
。将其替换为
T
可以解决此问题。
#include <tuple>
#include <array>
#include <cstdint>
#include <utility>

template <std::uint32_t ... I>
constexpr std::array<std::tuple<std::uint32_t, std::uint32_t, std::uint32_t>,
                     sizeof...(I)>
GenArrayTuple_helper(std::integer_sequence<std::uint32_t, I...>) {
    return { std::make_tuple(I, I * 2, I * 3 + 1) ... };
}

template <std::size_t SIZE>
constexpr std::array<std::tuple<std::uint32_t, std::uint32_t, std::uint32_t>,
                     SIZE> 
GenArrayTuple() {
    return GenArrayTuple_helper(std::make_integer_sequence<std::uint32_t, SIZE>{});
}