使用循环填充结构

Fill structure using loop

本文关键字:结构 填充 循环      更新时间:2023-10-16

我有一个C++结构

struct Line {
  int date;
  int time;
  float open;
  float high;
  float low;
  float close;
  float sd;
  float long_mo;
  float short_mo;
};

8 个字段。我想使用循环填充它。

int fields_count=1;
while (fields_count<=8) {
  // get digit from outer sourse. I dont need help here.
  // First iteration puts to 1 field, Second iteration puts to 2 field and so on up to last field of struct 
  fields_count++;
}

像这样:

#include<stddef.h>
struct Line {
  int date;
  int time;
  float open;
  float high;
  float low;
  float close;
  float sd;
  float long_mo;
  float short_mo;
};
char types [] = "iifffffff";
int offsets [] = {
  offsetof (Line, date),
  offsetof (Line, time),
  offsetof (Line, open),
  offsetof (Line, high),
  offsetof (Line, low),
  offsetof (Line, close),
  offsetof (Line, sd),
  offsetof (Line, long_mo),
  offsetof (Line, short_mo)
}
Line line;
for (int i = 0; i < 9; i++) {
  char *field_ptr = ((char*)&line) + offsets [i];
  if (types [i] == 'i')
    *(int*)field_ptr = readInt ();
  else if (types [i] == 'f')
    *(float*)field_ptr = readFloat ();
}

在 C++20 中,您可以使用扩展语句来迭代聚合:

auto my_line = Line{};
auto fields_count = std::size_t{0};
for...(auto& member : my_line) {
    member = get_digit(fields_count++);
}

您甚至可以获取正在迭代的成员的类型:

auto my_line = Line{};
auto fields_count = std::size_t{0};
for...(auto& member : my_line) {
    using type = std::remove_cvref_t<decltype(member)>;
    member = get_digit<type>(fields_count++);
}

可悲的是,C++中没有反射,所以没有一个好方法可以做你想做的事。

使用现代C++您可以执行以下操作:

#include <cstddef>
#include <iostream>
#include <tuple>
#include <utility>
struct Line
{
    int date;
    int time;
    float open;
    float high;
    float low;
    float close;
    float sd;
    float long_mo;
    float short_mo;
};
template <typename ...P, std::size_t ...I, typename F>
void for_each_tuple_elem_low(std::tuple<P...> t, std::index_sequence<I...>, F &&func)
{
    (void(func(std::get<I>(t))) , ...);
}
template <typename ...P, typename F> void for_each_tuple_elem(std::tuple<P...> t, F &&func)
{
    for_each_tuple_elem_low(t, std::make_index_sequence<sizeof...(P)>{}, func);
}
int main()
{
    Line obj;
    auto &[x1,x2,x3,x4,x5,x6,x7,x8,x9] = obj;
    auto tuple = std::tie(x1,x2,x3,x4,x5,x6,x7,x8,x9);
    int i = 0;
    for_each_tuple_elem(tuple, [&](auto &ref)
    {
        ref = i++;
    });
}

在这里,样板简化为键入结构化绑定的名称两次:x1,x2,x3,x4,x5,x6,x7,x8,x9