【问题标题】:Fill structure using loop [duplicate]使用循环填充结构[重复]
【发布时间】:2019-08-13 17:25:28
【问题描述】:

我有一个 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++;
}

【问题讨论】:

  • 您不能在 C++ 中迭代结构字段(很遗憾:()。
  • 如果所有字段都具有相同的类型,这会更容易。
  • if (fields_count == 1) line.date = sourse.as_int(); 等等

标签: c++


【解决方案1】:

类似这样的:

#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++ 座右铭“不用为不用的东西付费”的一个很好的例子。在这种情况下,C++ 没有反射(因为反射不是免费的;要正确支持反射需要大量基础设施和数据,可能永远不会使用)。 Mikhail 的示例展示了如何构建自己的反射,对于这种情况来说,这已经足够好了。
【解决方案2】:

在 C++20 中,您可以使用 expansion statements 迭代聚合:

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++);
}

【讨论】:

    【解决方案3】:

    遗憾的是,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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-28
      • 2016-12-28
      • 1970-01-01
      • 2022-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-11
      相关资源
      最近更新 更多