2

I have a class A that implements a function foo which takes as arguments two iterators (from any stl container). For what I've seen, the common approach is to use a template, as shown here:

class A{
    public:
        template <typename It>
        void foo(const It& begin, const It& end){
            // do stuff
        }
};

The problem is that I want to make foo virtual, and templates may not be virtual, but I don't want to have a class template like this:

template <typename It>
class A{
    public:
        void foo(const It& begin, const It& end){
            // do stuff
        }
};

because that would limit the use of foo in a single object to one kind of container.

My question: is there a way to use STL iterators as arguments without using templates, so that is possible to make such functions virtual and keep it working with any STL container?

Edit

Maybe this is a XY problem as said in the comments, so I'm going to explain the specific problem to see what you think.

I have an abstract class called LightSource with a pure virtual function void castLight(...) = 0. There are two classes that inherit from it and that implement the function, RadialLight and DirectedLight.

The problem is that to cast light I need a collection of objects Edge that specify segments in a 2D world, that may cast shadow. For the algorithm in castLight I need to iterate through that collection (not necessarily all of it) and do certain processing that is different in each kind of light.

Miguel
  • 2,130
  • 1
  • 11
  • 26
  • 1
    There are some ugly workarounds, although this smells of an XY problem. Templates are a form of compile-time polymorphism. Virtual functions are runtime polymorphism. – Drew Dormann Feb 09 '21 at 20:46
  • Perhaps you could ask how to solve the problem that you think requires virtual template functions? – Drew Dormann Feb 09 '21 at 20:52
  • @fabian That looks like a good approach, but I'm not sure it works for this case. I'm going to edit the question to be more specific with the problem – Miguel Feb 09 '21 at 21:12
  • What is the collection? You should be able to use: void foo(std::vector::const_iterator begin, ... if you want to "restrict" to iterators to specific collection. Note: you don't want const before the iterator, you most likely want const_iterator. – Zlatomir Feb 09 '21 at 21:36
  • @Zlatomir I'll take that into account, thanks. I guess that I will have to restrict the iterators to certain collection... – Miguel Feb 10 '21 at 09:45

1 Answers1

1

You can use a specific iterator type, such as std::vector<int>::iterator. Note that this may be different to std::vector<int>::const_iterator, std::deque<int>::iterator and std::vector<unsigned>::iterator, so you can end up with a multitude of overloads.

You can also use a type-erasing iterator, such as the iterators from boost::any_range, or any_range itself.

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • So the only way is restricting the type of the container and overloading... Well, thank you! – Miguel Feb 10 '21 at 09:46