Lets say I have an interface. Interface has begin and end functions because derived classes have to implement for-range functionality. The user will only use interface and will not know about the implementation of derived classes. I cannot use the same iterator for all derived classes (more specifically, operator++() is different) so I have to make an abstract base iterator class.
class BaseIterator
{
//...
public:
virtual Type operator*()
{
//Implementation
}
virtual bool operator!=(const BaseIterator&)
{
//Implementation
}
virtual BaseIterator& operator++() = 0;
}
//Interface
struct Interface
{
//other pure virtual functions
virtual BaseIterator& begin() = 0;
virtual BaseIterator& end() = 0;
}
In concrete classes who inherit the interface I am using, lets say one of them is class A, each has its own iterator which inherits from BaseIterator, and uses it to implement begin and end functions.
class A : public Interface
{
//...
class AIterator : public BaseIterator
{
AIterator& operator++()
{
//...
}
}
public:
AIterator& begin()
{
//...
}
AIterator& end()
{
//...
}
}
Similarly for other derived classes. The problem occurs when I try to use the for range loop with polymorphic types. For example (*)
Interface* c = Interface::makeA(); //assume for simplicity that there is static function in "Interface"
for(auto el : *c)
{
//do something with el
}
I get an error that I cannot instantiate the abstract class because of the pure virtual function operator++(). The reason I think this happens is in the implementation of for-range loop which goes something equivalently to the following:
auto && __range = range_expression ;
for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement;
}
I believe the problem lies in the "auto__begin == __range.begin()". begin returns reference to the BaseIterator, which because of the auto type deduction gets removed which in the end makes __begin type of BaseIterator and that is abstract class and cannot be instantiated. I know that this kind of behaviour can be implemented in Java. Am I missing something here? If not, how would you implement this but keeping the functionality in (*)?