Question

It's possible to iterate over a boost or std tuple, but can I iterate in an order determined at runtime, while still retaining type information?

Suppose my tuple was filled with objects of type Foo:

#include <tuple>

using namespace std;

template <typename ...> void bar(); // Definition omitted.

template <typename ... Ts>
struct Foo {
  void doit() { bar<Ts...>(); }
  int rank;
};

int main(int argc, char *argv[])
{
  auto tup = make_tuple(Foo<int,double>(),
                        Foo<bool,char,float>());
  get<0>(tup).rank = 2;
  get<1>(tup).rank = 1;
  return 0;
}

I would like to be able to traverse the list of Foo types, calling their doit methods, but in an arbitrary order defined by, say, the value of the rank member.

Was it helpful?

Solution

You will need to implement some type erasure in order to make this happen. Something along the lines of

template <typename ...> void bar(); // Definition omitted.

struct FooBase {
    virtual void doit() = 0;
    int rank;
};

template <typename ... Ts>
struct Foo : public FooBase {
  void doit() { bar<Ts...>(); }
};

int main(int argc, char *argv[])
{
  auto tup = make_tuple(Foo<int,double>(),
                        Foo<bool,char,float>());
  get<0>(tup).rank = 2;
  get<1>(tup).rank = 1;
  std::vector<FooBase*> bases;
  // fill bases
  // sort
  // call
  return 0;
}

There are other mechanisms you can apply which are functional, for example, and do not require modifying Foo, but they all boil down to the same principle- type erasure. I merely provided the simplest implementation of that erasure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top