Home > OS >  C iterator argument in abstract class
C iterator argument in abstract class

Time:11-04

I want to have an abstract class with a read and write method like:

template<typename Iterator>
virtual void read(uint64_t adr, Iterator begin, Iterator end) const = 0;    

template<typename Iterator>
virtual void write(uint64_t adr, Iterator begin, Iterator end) const = 0;

is there a way to achieve something like that?

Since there can't be a virtual template method, I thought about

  1. Get rid of the abstract class and use a template instead. In the template I would assume there is a read/write method taking an iterator.
  2. Make the abstract class a template too and pass the iterator type.

Is one of these ways a clean one? I'm on C 11 btw

CodePudding user response:

Is one of these ways a clean one?

Yes: use static polymorphism instead of virtual functions. When a type is passed via a template, it is not erased and therefore needs no pre-generated virtual tables, so you can cause further template instantiation - that's what your use-case begs for.

Solution 1 (recommended)

So, if your abstract class is used as just an "interface", get rid of it and write read/write in the "implementations" directly:

struct Impl {
  template<typename Iterator> void  read(uint64_t, Iterator, Iterator) const { /* work */ }
  template<typename Iterator> void write(uint64_t, Iterator, Iterator) const { /* work */ }
};

and replace usages of your implementation classes through that abstract class with

template<typename Impl> void use_any_impl(Impl&&) { /* work */ }

However, if your abstract class contains some logic/data which is meant to be inherited, you can keep the class but get rid of anything virtual:

class Abstract {
protected: ~Abstract() = default;
public:    constexpr int inherit_me() const { return 42; }
};

class Impl: public Abstract { /* read() and write() same as above */ };

/* use_any_impl() same as above */

Solution 2

If your templated Iterators always (or can be reduced to) lead to a raw array storage (e.g. one provided by std::vector<unsigned char>::data), which seems reasonable for raw read/write operations, you can just use raw pointers:

virtual void  read(uint64_t, unsigned char*, unsigned char*) const = 0;
virtual void write(uint64_t, unsigned char*, unsigned char*) const = 0;
  • Related