循环遍历成员变量

时间:2018-11-02 15:06:29

标签: c++

这是我的实现,用于在循环中顺序遍历类/结构中的成员变量,这是一个典型示例。我的实现看起来很丑陋,看起来像是用蛮力实现的。如何对其进行改进或推广。我想像在链接列表的node-> next或数组中一样前进变量?征求意见。预先感谢大师。

.as-console-wrapper { max-height: 100% !important; top: 0; }

已编辑:所有成员变量均为同一类型。

3 个答案:

答案 0 :(得分:2)

除了使用宏之外,还可以使用指向成员的指针。请注意,在C ++中,您不必typedef struct

struct Person {
    std::string name;
    std::string address;
    std::string phone;

    void print() const {
        std::cout << name << "-" << address << "-" << phone << '\n';
    }
};

int main()
{
    Person p;
    std::string str;
    std::stringstream ss{ "John London 9735048383" };
    std::vector<std::string(Person::*)> members = { &Person::name, &Person::address, &Person::phone };

    for (auto it = members.begin(); std::getline(ss, str, ' ') && it != members.end(); ++it) {
        std::invoke(*it, p) = str;
        // Traversing the member variables.  The member variables will take turn to set their values in order.
    }
    p.print();
}

只要您不关心停止流错误,就可以使invoke更加可口。

for (auto member : members)
{
    std::getline(ss, invoke(member, p), ' ');
}

答案 1 :(得分:0)

如果您确实希望可以推广一些东西,并且愿意使用宏,则可以使用higher order macros。对于您的情况,您首先要添加一个宏,该宏声明您的struct的所有字段及其索引:

#define FOREACH_FIELD(OP)                       \
  OP(0, name)                                   \
  OP(1, address)                                \
  OP(2, phone)

然后,您将使用此宏来实现您的Person结构:

struct Person {
#define DECLARE_VAR(index, name) std::string name;
  FOREACH_FIELD(DECLARE_VAR)
#undef DECLARE_VAR

  void setField(int i, const std::string& value) {
    switch (i) {
#define SET_FIELD(index, name) case index: name = value; break;
    FOREACH_FIELD(SET_FIELD)
#undef SET_FIELD
      };
  }

  void print() {
#define PRINT_FIELD(index, name) \
    std::cout << #name << ": '" << name << "'" << std::endl;
    FOREACH_FIELD(PRINT_FIELD)
#undef PRINT_FIELD
  }
};

它看起来很丑陋,我建议您在采用上述技术之前先认真考虑一下。通常,在C ++中避免使用宏。它使您的代码更难阅读,但是,如果您有很多字段,那么可以使用它。它可以使您的代码更具可维护性。毕竟,要添加新字段,只需更新FOREACH_MACRO

仔细使用此技术。

答案 2 :(得分:0)

根据{{​​3}}的建议,

std :: array似乎对我有用,这似乎是迄今为止最简单的解决方案。我猜std :: map将具有一个额外的优势。

typedef struct {
    std::array<string, 3> data;

    void print() const {
        std::cout << data[0] << "-" << data[1] << "-" << data[2] << '\n';
    }
} Person ;

int main()
{
    Person p;
    string str;
    stringstream ss{ "John London 9735048383" };

    int idx = 0;
    while (std::getline(ss, str, ' ')) {
        p.data[idx++] = str; 
    }
    p.print();

}