I have a class baseNoCrtpIterator that holds one member baseNoCrtp _base, among others.
Class baseNoCrtp has several simply derived classes derived[n]NoCrtp, where [n] denotes a number 1,2,... These classes do not add any data members to baseNoCrtp, only some functionality.
I want that, during construction of a baseNoCrtpIterator, member _base is assigned one of derived[n]NoCrtp, depending on another value dclass passed to the constructor.
Is that possible?
I tried a constructor like
baseNoCrtpIterator::baseNoCrtpIterator(const int dclass) :
    _base(dclass)       // Point #8
{
    if (dclass == 0) {
        derived1NoCrtp* d1n = new derived1NoCrtp(0);
        _base = *d1n;        // Point #9
    }
    else if (dclass == 1) {
        derived2NoCrtp* d2n = new derived2NoCrtp(1);
        _base = *d2n;
    } else {
        cout << "Unknown derived class: " << dclass << endl;
        throw runtime_error("Unknown derived class");
    }
};
This doesn't work, and I probably have to fix #8 (I guess I have to remove it from the initializer list), and #9, since I don't have operator= (I could write it, but I guess it doesn't solve my problem).
Note: I guess CRTP might be an alternative. But I see a couple of problems:
- All uses of baseNoCrtpIteratorhave to be replaced bybaseNoCrtpIterator<T>. Thus, downstream, all functions, classes, etc., that usebaseNoCrtpIteratorwill have to be "templetized". This means huge changes in existing code.
- I would not be able to hold all objects of class baseNoCrtpand derived in a single container. That is part of the changes mentioned above.
TL;DR
I have two hierarchies of (base + n simply derived) classes. One is a "main" hierarchy, and the other is an "iterator" hierarchy, meant to iterate over the main.
The base class for the iterators refers to the base class for the main in #1
class baseNoCrtpIterator {
public:
    baseNoCrtpIterator(const baseNoCrtp& base, const int dclass);
    virtual ~baseNoCrtpIterator() {};
    const baseNoCrtp& operator*() const { return *operator->(); };
    const baseNoCrtp* operator->() const { return &_base; };
private:
    baseNoCrtp _base;   // Point #1
    int _index;
};
and its constructor is
baseNoCrtpIterator::baseNoCrtpIterator(const structure& s, const int dclass) :
    _base(s, dclass),
    _index(0) { };
where dclass indicates the derived class of _base (that is not enough, as will be shown later).
The derived iterator classes are like this (derived1... is associated with dclass=0, and so on)
class derived1NoCrtpIterator : public baseNoCrtpIterator {         // derived1...
public:
    derived1NoCrtpIterator(const baseNoCrtp& base) : baseNoCrtpIterator(base, 0) {};   // ... dclass=0
    virtual ~derived1NoCrtpIterator() {};
    const derived1NoCrtp& operator*() { return *operator->(); }
    const derived1NoCrtp* operator->() {                             // Point #2
        const baseNoCrtp* bnp = baseNoCrtpIterator::operator->();    // Point #3
        return static_cast<const derived1NoCrtp*>(bnp);              // Point #4
    }
};
The problem is when using something like
for (derived1NoCrtpIterator d1ni(sconst); ...) {
    const derived1NoCrtp& d1nr = *d1ni;   // Point #5
    ...
Point #5 leads to #2.
In #3 we extract a pointer to member baseNoCrtp.
But then the static_cast downcast in #4 is undefined behavior.
This could be solved if the constructor baseNoCrtpIterator::baseNoCrtpIterator assigned to baseNoCrtp objects of the derived classes derived1NoCrtpIterator, etc., instead of the base class.
I tried to replace the constructor with something like
baseNoCrtpIterator::baseNoCrtpIterator(const structure& s, const int dclass) :
    _base(s, dclass),        // Point #8
    _index(0) {
    if (dclass == 0) {
        derived1NoCrtp* d1n = new derived1NoCrtp(s, 0);
        _base = *d1n;        // Point #9
    }
    else if (dclass == 1) {
        derived2NoCrtp* d2n = new derived2NoCrtp(s, 1);
        _base = *d2n;
    } else {
        cout << "Unknown derived class: " << dclass << endl;
        throw runtime_error("Unknown derived class");
    }
};
This doesn't work, and I probably have to fix #8 (I guess I have to remove it from the initializer list), and #9, since I don't have operator= (I could write it, but I guess it doesn't solve my problem).
How can I achieve this assignment to _base of objects of derived classes, depending on dclass?
Since this is a boiled down example of a very large code that I have to fix, I am in principle not interested in other methods that require extensive modifications of the code. For instance, if CRTP might be a solution, it probably involves huge changes. I know the current way might be a somewhat contrived form of iterating the main hierarchy, but this is what I received.
The "main" classes are (here it is not relevant what structure is):
class baseNoCrtp {
public:
    baseNoCrtp(const structure& s, const int dclass) :
        _structure(s), _derivedClass(dclass) { };
    virtual ~baseNoCrtp() {};
public:
    int getDerivedClass() const { return _derivedClass; }
    const structure& getStructure() const { return _structure; };
protected:
    const structure& _structure;
private:
    friend class baseNoCrtpIterator;
    int _derivedClass;
};
class derived1NoCrtp : public baseNoCrtp {
public:
    derived1NoCrtp(const structure& s) : baseNoCrtp(s, 0) {};
    virtual ~derived1NoCrtp() {};
    // Add whatever extra methods
};
