0

Here's an example showing what I am essentially trying to do

// Example program
#include <iostream>
#include <vector>

struct base_type
{
    static const uint64_t type_id = 0x0;
};

struct A : public base_type
{
    static const uint64_t type_id = 0xA;
};

struct B : public base_type
{
    static const uint64_t type_id = 0xB;
};

struct C : public base_type
{
    static const uint64_t type_id = 0xC;
};


template <class... Args>
struct processor
{
    void process(Args... args);

    // NEED HELP WITH HOW THIS WOULD WORK
    // Essentially I want a fucntion that can extract
    // the type_id of each of the template parameters
    std::vector<uint64_t> get_type_ids()
    {
        // What should go in here?
    }
};

int main()
{
    processor<A, B> my_processor;
    B b;
    C c;
    // Here's the part that I am stuck on
    // THIS IS PSEUDOCODE
    if (b.type_id in my_processor.get_type_ids() and c.type_id in my_processor.get_type_ids())
    {
        my_processor.process(b, c);
    }
    else
    {
        std::cout << "One of the arguments to process was not the correct type" << std::endl;
    }
}

And in this example this would print out the error message. Is there any way to do this? The reason that I am running into this problem is that I am receiving a number of base_type objects which are being passed to process but I need to check beforehand whether base_type can be safely cast into the derived type. Everything actually does have a type_id already so I'm hoping that can save me.

Nick Chapman
  • 4,402
  • 1
  • 27
  • 41
  • Possible duplicate: https://stackoverflow.com/questions/351845/finding-the-type-of-an-object-in-c – Jaege May 11 '18 at 18:40
  • @Jaege in that case the validation is happening _inside_ the class but in this case I need to validate outside of the class and as a result need to recover information about the template parameters. – Nick Chapman May 11 '18 at 18:42

1 Answers1

0

Here's how I would do this:

instead of using an a scalar type for the type ID, like so:

static const uint64_t type_id = 0x0;

I would create a dedicated type with a constructor:

static const my_meta_type type_id;

my_meta_type A::type_id{0x00};

Where my_meta_type would look something like this:

class my_meta_type {
  static std::vector<my_meta_type const*>& registered_types(); //Meyer's singleton
  uint64_t id_;
public:
  my_meta_type(uint64_t id) 
    : id_(id) {
    registered_types().emplace_back(this);
  }
};

std::vector<my_meta_type*>& my_meta_type::registered_types() {
  static std::vector<my_meta_type const*> instance;
  return instance;
}

What this will do is that during initialization, the constructors of my_meta_type will run, putting the pointer instances in the vector<my_meta_type*>. Because this is all happening during initialization, we need to make sure init order doesn't cause us issues, thus we use a Meyer singleton to resolve the potential conflicts.

From there, all you have to do is retrieve the ids from the vector during program execution.