0

I am trying to create an easy-to-use interface for array indexing in C++. Unfortunately, I just cannot get my code working. And I think the problem is regrading to C++ does not allow me to cast a base class back to the derived class. However, I am not sure why that happens. Please help me with that.

Here is the code.

#include <iostream>
#include <vector>

enum index_type {
    single_value,
    sequence,
};


class idx {
protected:
    index_type t;
public:
    idx(index_type _t);
    virtual void print_out();
};

class single_idx:public idx {
private:
    int sidx;
public:
    single_idx(int _sidx);
    void print_out();
};


class multiple_idx:public idx {
private:
    std::vector<int> midx;
public:
    multiple_idx(std::vector<int> _midx);
    void print_out();
};

idx::idx(index_type _t):t(_t){
    switch (t) {
        case (single_value):{
        std::cout << "single_value\n";
        break;
        }

        case (sequence):{
        std::cout << "multiple_value\n";
        break;
        }
    }
}

single_idx::single_idx(int _sidx):sidx(_sidx), idx(single_value){}

multiple_idx::multiple_idx(std::vector<int> _midx):midx(_midx), idx(sequence){}

void idx::print_out() {
    std::cout << "lalala\n";
    switch (t) {
        case (single_value):{
        std::cout << "casting to single\n";
        dynamic_cast<single_idx*>(this)->print_out();  // ERROR happens here!!!
        break;
        }

        case (sequence):{
        std::cout << "casting to multiple\n";
        dynamic_cast<multiple_idx*>(this)->print_out();
        break;
        }
    }
}

void single_idx::print_out() {
    std::cout << "single value: ";
    std::cout << sidx << "\n";
}

void multiple_idx::print_out() {
    std::cout << "multiple value: ";
    for (int i : midx) {
        std::cout << i << " ";
    }
    std::cout << "\n";
}

void f(std::initializer_list<idx> a) {
    for (idx t : a) {
        t.print_out();
    }
}

int main()
{
    f({single_idx(1), single_idx(2)});
}
  • Once you added the object to the vector you pass to the function `f`, all you have are objects of the `idx` class. There's no information about what classes you might once have had. This is what the duplicate is about. – Some programmer dude Mar 10 '20 at 06:53
  • A `dynamic_cast` ought to do the trick (or some sorta downcast). IMHO though, you're in for a lot of grief trying to design "do-it-all" base interfaces of this sort. You are trying too hard to solve too many problems with a singular design in my book. That sounds epic and awesome and badass, but I really think you'll get further in your career tackling narrower sets of problems with narrower (but still sorta general) solutions. –  Mar 10 '20 at 06:53
  • To solve your problem, you need to use a vector of references (with the help of e.g. [`std::ref` and `std::reference_wrapper`](https://en.cppreference.com/w/cpp/utility/functional/ref)) or pointers (to the base object). Then you can let the virtual dispatch sort it out and you don't need the enumeration anymore. – Some programmer dude Mar 10 '20 at 06:54
  • The problem you are trying to solve already has a much general solution in the standard library called [`valarray`](https://en.cppreference.com/w/cpp/numeric/valarray). – Tanveer Badar Mar 10 '20 at 07:30
  • Actually what I am trying to create is an indexing library for multi-dimensional array in C++, which can provide me with a numpy-like indexing interface. In this case, I want to be able to pass two types of index into the indexing function (single index and multiple index). Is there any work around in C++ can let me do that? – Alexander Lee Mar 10 '20 at 14:33

0 Answers0