I have an abstract class like so:
class A
{
public:
void func() = 0;
};
Can I force its implementations to have a nested iterator class too?
#include <iterator>
template<typename T>
class A
{
public:
class Iterator : public std::iterator<std::forward_iterator_tag, T>
{
};
virtual Iterator begin() const = 0;
virtual void func() = 0;
};
template<typename T>
class B : public A<T>
{
public:
B() {}
class Iterator : public std::iterator<std::forward_iterator_tag, T>
{
};
Iterator begin() const
{
return Iterator();
}
virtual void func()
{
}
};
int main()
{
B<int> b;
}
I just want to know if this is possible, and if it is, what am I missing? Since the iterator class will depend on how the class A is implemented, I don't know if a formal implementation is possible.
Try this one:
template<typename T>
class A
{
public:
class Iterator : public std::iterator<std::forward_iterator_tag, T>
{
public:
virtual void DoSomething() = 0;
};
virtual Iterator * begin() const = 0;
virtual void func() = 0;
};
template<typename T>
class B : public A<T>
{
public:
B() {}
class BIterator : public A<T>::Iterator
{
public:
void DoSomething()
{
std::cout << "Hello world from B::BIterator!";
}
};
A<T>::Iterator * begin() const
{
return new BIterator();
}
virtual void func()
{
}
};
int main(int argc, char * argv[])
{
B<int> b;
A<int>::Iterator * iter = b.begin();
iter->DoSomething();
delete iter;
getchar();
}
Note, that this won't force B to implement a new instance of A<T>::Iterator
, but simply to provide one. Developer may, for instance, implement a single generic iterator and return it from all A<T>
-derived classes. But I guess, that should be enough, shouldn't it?
Edit: In response to comments
You should return the iterator by pointer. Since you want it to be an abstract class, you cannot declare instance of it like:
A<int>::Iterator iter = b.begin(); // Error: cannot instantiate abstract class
// A<int>::Iterator
You can do it however if you resign from A<T>::Iterator
being an abstract class. But then you won't be able to force one to descend from A<T>::Iterator
...
I just want to know if this is possible, and if it is, what am I missing?
Well, no, unless you define at least a pure virtual member function for Iterator
you cannot force derived class to have one.
The way the standard library solves this is to use concepts. They are constraints on template argument which in turn define common interfaces for common objects.
Take for example the Container
concept: it requires a generic type T
to have the following valid expressions:
T::reference
T::const_reference
T::iterator
In this way, you could define a function:
template<class Container>
void do_something(Container c) {
Container::iterator it = c.begin();
// etc
}
and expect it to work with every type that fit the Container
concept. In fact, the above code happily compiles using it with 3 different standard containers (namely vector
, list
and deque
).
In this way you, as a C++ user, can create your own containers, make it fit the requirements for concept you want to support and be able to use all the algorithms that any other containers have, automatically. No interface required, no public inheritance, nothing.
Not to mention that an explicit Concept Lite proposal is being discussed these days as to implement these "interfaces" in a more explicit manner.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With