C++0x: How can I access variadic tuple members by index at runtime?

后端 未结 4 743
既然无缘
既然无缘 2021-01-14 07:38

I have written the following basic Tuple template:

template 
class Tuple;

template 
struct TupleIndex         


        
4条回答
  •  梦谈多话
    2021-01-14 08:22

    I was having a hard time wrapping my head around the solutions I was finding, so I fashioned one of my own. All of the members in my tuple derive from the same class, so I adapted my previous solution by adding a base type parameter to my tuple class and using pointers-to-members:

    template 
    class Tuple;
    
    template 
    struct TupleIndexer;
    
    template 
    struct TupleOffsets;
    
    template 
    struct TupleOffsets {
    
        TupleOffsets() { Init::*>(offsets); }
        Base Tuple::* const& operator[] (uintptr_t i) const { return offsets[i]; }
    
        template 
        static void Init(PtrType* offsets);
    
        private:
        Base Tuple::* offsets[sizeof...(Tail) + 1];
    
    };
    
    template 
    template 
    void TupleOffsets::Init(PtrType* offsets) {
    
        *offsets = PtrType(&Tuple::element);
        TupleOffsets::Init(++offsets);
    
    }
    
    template 
    struct TupleOffsets {
    
        TupleOffsets() {}
        template 
        static void Init(PtrType* offsets) {}
    
    };
    
    template 
    class Tuple : public Tuple {
    
        private:
        Head element;
    
        public:
        Base* Get(uintptr_t i) {
            return &(this->*offsets[i]);
        }
    
        template 
        typename TupleIndexer::Type& Get() {
            return TupleIndexer::Get(*this);
        }
    
        uintptr_t GetCount() const {
            return sizeof...(Tail) + 1;
        }
    
        private:
        static const TupleOffsets offsets;
    
        friend struct TupleOffsets;
        friend struct TupleIndexer;
    
    };
    
    template 
    const TupleOffsets Tuple::offsets;
    
    template 
    class Tuple {
    
        public:
        uintptr_t GetCount() const {
            return 0;
        }
    
    };
    
    template 
    struct TupleIndexer {
    
        typedef Head& Type;
    
        static Type Get(Tuple& tuple) {
            return tuple.element;
        }
    
    };
    
    template 
    struct TupleIndexer {
    
        typedef typename TupleIndexer::Type Type;
    
        static Type Get(Tuple& tuple) {
            return TupleIndexer::Get(*(Tuple*) &tuple);
        }
    
    };
    

    The following now works nicely, which is what I was ultimately shooting for:

    struct Base {
        virtual void print() = 0;
    };
    
    struct Derived1 : public Base {
        virtual void print() { cout << "I'm the first derived class!" << endl; }
    };
    
    struct Derived2 : public Base {
        virtual void print() { cout << "Woohoo!  I'm the second derived class!" << endl; }
    };
    
    ...
    
    Tuple var;
    var.Get(0)->print();
    var.Get(1)->print();
    

提交回复
热议问题