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
- 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.
- 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 template
d Iterator
s 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;