迭代一个类列表

时间:2016-12-28 15:30:51

标签: c++

我希望能够遍历从共同祖先继承的类列表。

我想要的缩小版本(类似Python的语法,因为我来自的语言):

int outcome = 0;

PlayerTypeOne player_one();
if doThingWithPlayer(player_one, some, other, variables){
    outcome++;
}
PlayerTypeTwo player_two();
if doThingWithPlayer(player_two, some, other, variables){
    outcome++;
}
PlayerTypeThree player_three();
if doThingWithPlayer(player_three, some, other, variables){
    outcome++;
}

如果这不是进行此类操作的首选方式,那么非常欢迎有关我应该如何继续的建议。

我想避免的代码是:

<button>

2 个答案:

答案 0 :(得分:1)

您正在寻找factory design pattern

Player *create_by_name(const std::string &what)
{
   if (what == "PlayerTypeOne")
         return new PlayerTypeOne;
   if (what == "PlayerTypeTwo")
         return new PlayerTypeTwo;

   // ...
}

等等。您似乎也想要做的是为每个子类的构造函数提供参数。

如果所有子类都使用相同的构造函数参数,则这变得微不足道:将参数传递给工厂,并将它们转发给构造函数。

如果需要为构造函数支持不同的参数,这会变得更加复杂。我建议你从小开始,为你的对象实现一个简单的工厂,没有构造函数参数,或者只有几个对所有子类都相同。一旦你掌握了基本原理,你就可以担心处理复杂的角落案例。

然后,只需要一个类名数组,遍历数组,然后调用工厂。这应该与伪Python代码具有相似的结果。

答案 1 :(得分:1)

C ++没有提供内置的内省,所以你不能只获取代表你的类的对象并用它们创建实例。

你可以做的是使用元编程:

// A list of types
template <class...> struct pack { };

// Calls f with one default-constructed instance of each T
template <class... Ts, class F>
void construct_each(pack<Ts...>, F &&f) {

    // Classic pre-C++17 expansion trick
    using ex = int[];
    (void)ex{(f(Ts{}), void(), 0)..., 0};

    // C++17 version
    // (void)(f(Ts{}), ...);
}

// ...

using Players = pack<PlayerTypeOne, PlayerTypeTwo, PlayerTypeThree>;

void foo() {
    int outcome = 0;

    construct_each(Players{}, [&](auto &&player) {
        if(doThingWithPlayer(player, some, other, variables))
            ++outcome;
    });
}

See it live on Coliru