在相同类型的字段上迭代

Iterating over fields of the same type

本文关键字:迭代 字段 同类型      更新时间:2023-10-16

让您有以下类:

class Data
{
public:
    int a;
    int b;
};
class DataOther
{
public:
    int a;
    int b;
};
class Line
{
public:
    Data Right;
    Data Left;
};
class LineOther
{
public:
    DataOther Right;
    DataOther Left;
}

我有很多这样的课程,当我想在数据的两个"侧面"上运行代码时,我通常会做这样的事情:

enum class Side { RIGHT, LEFT };
template<typename T>
auto GetBySide(const Side &side, T &data) -> decltype(data.Right) & 
{ 
    return side == Side::Left ? data.Left : data.Right; 
}

,然后在代码中:

Line l;
LineOther lOther;
for(auto &side: {Sides::LEFT, Sides::Right})
{
      auto &d = GetBySide(side, l);
      auto &dOther = GetBySide(side, lOther);
      // Do some stuff with the data
}

现在的下一侧是它是运行时的,因此无法进行太多的优化,尽管我想编译器可能会展开循环。

关于如何构建代码的其他想法?

如果您担心展开,则可以替换:

Line l;
LineOther lOther;
for (auto &side: {Sides::LEFT, Sides::Right})
{
      auto &d = GetBySide(side, l);
      auto &dOther = GetBySide(side, lOther);
      // Do some stuff with the data
}

诸如:

之类的东西
template <Side side>
void foo(Line& l, LineOther& lOther) {
      auto &d = GetBySide(side, l);
      auto &dOther = GetBySide(side, lOther);
      // Do some stuff with the data
}

Line l;
LineOther lOther;
foo<Sides::LEFT>(l, lOther);
foo<Sides::Right>(l, lOther);

"我有很多这样的类,"似乎您只能留下其中一个。或至少利用继承或其他技术来避免重复:

// Declare base class instead of copypasting fields.
class BaseLine
{
public:
    int Right{};
    int Left{};
};
class Line: public BaseLine
{};
class LineOther: public BaseLine
{};
int main()
{
    Line l;
    l.Right = 45; l.Left = 89;
    LineOther lOther;
    lOther.Right = 74; lOther.Left = 33;
    // Use pointer to member to iterate over fields.
    for(auto p_side: {&BaseLine::Right, &BaseLine::Left})
    {
       ::std::cout << (l.*p_side) << ::std::endl;
       ::std::cout << (lOther.*p_side) << ::std::endl;
    }   
}

在线编译器