Reputation: 200
I need to make some specific constructor which gets two iterators: start iterator and end iterator.
I have some code and its works:
#include <iostream>
#include <vector>
using namespace std;
template<typename T>
class A
{
public:
T a[10];
typename std::vector<T>::iterator itStart, itEnd;
A(typename vector<T>::iterator itStart, typename vector<T>::iterator itEnd):itStart(itStart),itEnd(itEnd){}
void see()
{
int i=0;
while(itStart != itEnd)
{
cout<<*itStart<<endl;
a[i] = *itStart;
itStart++;
i++;
}
}
};
template <typename Iterator>
double Sum( Iterator begin, Iterator end );
int main()
{
cout << "Hello world!" << endl;
vector<int> v;
v.push_back(1);
v.push_back(1);
v.push_back(2);
v.push_back(3);
class A<int> a(v.begin(),v.end());
a.see();
return 0;
}
But I want to make constructor arguments work with all STL containers(like Set,List,Map etc.) and with normal arrays(normal pointers). So can I make it in generic template way? Something like that:
template<typename T>
class A
{
public:
iterator<T> itStart, itEnd;
A(iterator<T> itStart, iterator<T> itEnd):itStart(itStart),itEnd(itEnd){}
void see()
{
while(itStart != itEnd)
{
cout<<*itStart<<endl;
itStart++;
}
}
};
I know code the above is wrong but I want to explain my idea.
Of course I can overload constructor but I am too lazy to that. Too many STL containers. Is some template way to solve that issue?
Upvotes: 2
Views: 317
Reputation: 1041
Perhaps you could make use of the notion of an input sequence (iseq).
An input sequence is denoted by a pair of iterators (begin and end).
Of course, you would need to create overloads of all the STL algorithms that accept an iseq instead of a pair of iterators.
Then your example could just use for_each (overloaded to accept an iseq).
Example code can be found in TC++PL 3rd edition (Stroustrup) section 18.3.1.
Upvotes: 0
Reputation: 56549
Looking at one of STL's things such as std::fill
:
template< class ForwardIt, class T >
void fill( ForwardIt first, ForwardIt last, const T& value );
we can be inspired:
template<typename ITR, typename T>
class A
{
A(ITR itStart, ITR itEnd):itStart(itStart),itEnd(itEnd){}
...
Upvotes: 0
Reputation: 133122
Obviously you need to make the iterator type a template argument to your class
template<class T, class Iter>
class A
{
Iter first, last;
A(Iter first, iter last):first(first), last(last){}
};
But now it becomes uncomfortable to explicitly specify the template argument
A<int, vector<int>::iterator > a;
To avoid that, simply create a factory function
template<class T, class Iter>
A<T, Iter> make_A(Iter first, iter last)
{
return A<T, Iter>(first, last);
}
Now, instead of directly creating an object of A, you can use the function
auto my_A = make_A<int>(v.begin(), v.end());
Upvotes: 1