为什么我不能在 constexpr lambda 函数中使用 std::tuple
Why can't I use a std::tuple in a constexpr lambda function
我有以下代码:
#include <string_view>
#include <array>
#include <tuple>
struct Variable
{
size_t index;
std::string_view name;
std::tuple<float, float> bounds;
};
constexpr std::array<Variable, 3> myarray = [](){
std::array<Variable, 3> res{};
std::array<std::string_view, 3> strings = {"myvar1", "myvar2", "myvar3"};
std::array<std::tuple<float, float>, 3> bounds = {{{0,1}, {1,2}, {2,3}}};
for (std::size_t i = 0; i != res.size(); ++i) {
res[i] = {i, strings[i], bounds[i]};
}
return res;
}();
但是由于std::tuple
,此代码无法编译。我不能在 lambda 函数中使用std::tuple
的原因是什么?
我正在使用
c++ -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -g -o main.o -c main.cpp
以编译代码。
编译器的版本为:gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
我得到的错误是:
../main.cpp:53:3: error: call to non-constexpr function ‘<lambda()>’
}();
^
../main.cpp:44:51: note: ‘<lambda()>’ is not usable as a constexpr function because:
constexpr std::array<Variable, num_vars> xrt = [](){
^
../main.cpp:51:39: error: call to non-constexpr function ‘Variable& Variable::operator=(Variable&&)’
res[i] = {i, strings[i], bounds[i]};
^
../main.cpp:16:8: note: ‘Variable& Variable::operator=(Variable&&)’ is not usable as a constexpr function because:
struct Variable
^~~~~~~~
tuple
和pair
都没有在 C++17 中分配 constexpr。
但即使是包含一对值的普通结构也可以完成这项工作。如果需要,您可能希望实现自己的 constexpr 兼容结构。您需要的没有绒毛的琐碎版本:
struct Couple {
float a, b;
};
struct Variable
{
size_t index;
std::string_view name;
Couple bounds;
};
constexpr std::array<Variable, 3> myarray = [](){
std::array<Variable, 3> res{};
std::array<std::string_view, 3> strings = {"myvar1", "myvar2", "myvar3"};
std::array<Couple, 3> bounds = {{{0,1}, {1,2}, {2,3}}};
for (std::size_t i = 0; i != res.size(); ++i) {
res[i] = {i, strings[i], bounds[i]};
}
return res;
}();
可以按照将来标准使用tuple
的方式排列代码
std::tuple
的赋值运算符直到 C++20 才constexpr
。如果避免使用赋值运算符并就地构造元组,则代码将编译:
constexpr std::array<Variable, 3> myarray = [](){
std::array<std::string_view, 3> strings = {"myvar1", "myvar2", "myvar3"};
std::array<std::tuple<float, float>, 3> bounds = {{{0,1}, {1,2}, {2,3}}};
std::array<Variable, 3> res { {
{0, strings[0], bounds[0]},
{1, strings[1], bounds[1]},
{2, strings[2], bounds[2]}
} };
return res;
}();
从 C++14 开始,std::tuple
的构造函数是constexpr
的(至少是那些不接受分配器的构造函数(,所以你可以使用其中一个来代替赋值运算符。
开始向类中添加constexpr
构造函数
struct Variable
{
size_t index{};
std::string_view name{};
std::tuple<float, float> bounds{};
constexpr Variable(size_t i, std::string_view str)
: index{i}, name{str}, bounds{i, i + 1} {}
};
然后,您可以使用几个利用 std::integer_sequence 的模板函数来构造数组。
template <class Element, std::size_t... I, typename... ArgsType>
constexpr auto make_array_with_indices_impl(std::index_sequence<I...>, ArgsType... args)
{
return std::array<Element, sizeof...(args)>{
Element(I, args)...
};
}
template <class Element, typename... ArgsType>
constexpr auto make_array_with_indices(ArgsType... args)
{
return make_array_with_indices_impl<Element>(
std::index_sequence_for<ArgsType...>{}, args...
);
}
这是它们的用法示例。
相关文章:
- 在 std::tuple 上使用 std::variant 的问题
- 在构造函数中使用可变参数初始化 std::tuple
- 转发复制的 std::tuple
- 我可以将新的 std::tuple 放入内存映射区域,并在以后读回吗?
- std::tuple 可以根据其值在编译时/运行时排序吗?
- 返回 std::tuple 中的引用和值
- 带有引用的std::tuple在clang中编译失败,但在gcc中编译失败
- 尝试实现std::tie和std::tuple的小版本
- std::tuple默认构造函数,带有move可构造元素
- 来自带有 std::tuple 的地图
- 如何从 std::async 任务返回 std::tuple
- 为什么 std::when_any 使用 std::tuple 而不是 std::vector 作为其结果类型?
- 为什么 std::integral_constant 在爆炸 std::tuple 时是必需的?
- 如何在std :: tuple中的每个元素上应用constexpr函数
- 如果创建支持返回可变参数类型列表的通用模板 API,我应该使用 std::tuple 还是其他东西?
- 类型安全 - all_of/ any_of/ none_of for std::tuple
- 将__m128i值转换为 std::tuple
- 使结构的行为类似于 std::tuple
- std::tuple faster than std::array?
- C++ 在标准::unordered_map中设置 std::tuple 值