Click here to Skip to main content
15,883,705 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Sorry if my English or my coding conventions are bad.
std::list is the STL list.
I am trying to make a library that will use std::list<>::iterator and std::list<>::reverse_iterator seamlessly to the user according to his choice.
First, I wouldn't like to implement all std::list<>::iterator methods. So I'll inherit them to my class:
C++
template <class realIter> class directedListTypeIter : public realIter

The user will instantiate the directedListTypeIter with 2 possible templates:
C++
directedListTypeIter<std::list<value>::iterator>
directedListTypeIter<std::list<value>::reverse_iterator>

It means that I should create the following assignment operators (or copy constructor):
C++
directedListTypeIter& operator=(std::list<value>::reverse_iterator &constructorIter) {
  ((std::list<value>::reverse_iterator*)this)->operator=(constructorIter);
  return *this;
}
directedListTypeIter& operator=(std::list<value>::iterator &constructorIter){
  ((std::list<value>::reverse_iterator*)this)->operator=(constructorIter);
  return *this;
}

I need all this assignment operators for the following function implementation, and other similar implementations.
C++
directedListTypeIter begin(std::list<value>& userList){ 
  directedListTypeIter<realIter> retVal;
  if (someCheck()){
    retVal = userList.begin();
  } else {
    retVal = userList.rbegin();
  }
  return retVal;
}

In different words- In order to implement the begin() function, and other similar functions I need, I should implement the assignment operator (or copy constructor).

Here is my questions:
1. All this depends on the existence and usage of the "value" struct. How can I remove this dependency?

2. If I had more possible inherited types, should I have been creating new assignment operator (or copy constructor) for each type? isn't the template programming meant not to copy that code? How can I make the same without copying the code to each operator?

3. What should I add so the following:
C++
directedListTypeIter& operator=(realIter &constructorIter){
  ((realIter*)this)->operator=(constructorIter);
  return *this;
}

would compile- without adding something that lists all possible inherited values?

thanku.

p.s. This topic is about how to template the inheritance, and not about achieving the use of both iterator types in one interface. I mean- the "C++ Standard Library list" use case is just an example to better explain my issue.
Posted

By doing that, you are going against the design principles of STL.

Maybe you can consider doing something like:

C++
template <class F> void Iterate(const T &container, F func, bool forward)
{
  if (forward)
  {
     std::for_each(container.begin(), container.end(), func);
  }
  else
  {
    std::for_each(container.rbegin(), container.rend(), func);
  }
}


And when you have to iterate you can do something like:

C++
Iterate(userList, someFunction, someCheck());


If you are using a recent compiler, you might even use lambda instead of function objects...

By using a simple function like this one, you can simplify calling code if you have to select direction a lot of time on a whole container.

Depending on what is similar and whjat varies, you might adapt the code so that common logic is inside the iterate function. Or it everything varies a lot, then you might simply uses for_each directly.

You might also look at boost range: http://www.boost.org/doc/libs/1_53_0/libs/range/doc/html/index.html[^]. I haven't uses them but it might be something that might help you or maybe give you some idea.
 
Share this answer
 
v3
Comments
debil123 13-Apr-13 17:51pm    
It is not the answer I was looking for. Did you read the "p.s." thing? It states that the example is just to clarify my question- how to template the inherited class.
I don't think inheritance is the right tool for the job in this case. Would something like the following give you what you need with less issues.

< template typename T, template typename IteratorType = ForwardIteratorType >
struct MyContext
{
  public:

  typedef std::list< T > List;
  typedef std::list< T >::iterator Iterator;
};

< template typename T, ReverseIteratorType >
struct MyContext
{
  public:

  typedef std::list< T > List;
  typedef std::list< T >::reverse_iterator Iterator;
};


This is called partial template specialisation and is available in all recent C++ compilers, MSVC from 2010 should work before that more of a lottery back to VC6 none at all.

MyContext< int, ReverseIteratorType >::Iterator rit;
MyContext< int >::Iterator it;


Shold now give you reverse and standard iterators for a list of int without having to override or inherit anything.
The great thing with templates is you don't have to write any 'real' code until and unless you want to change or add functionality. All you need is the right incantation of template type declarations.
 
Share this answer
 
Comments
debil123 11-Apr-13 12:03pm    
Thanku for your answer. It may be a solution for the example issue.
But, it is not applicable in my case.
1. I can't use myContext instead of std::list.
2. when compiling templated code, I understand that the compiler duplicates the code. It means that both types of iterators can't share a single list. Because it defined twice. But, maybe we don't need that definition at all.



Anyway, it is not the answer I was looking for.
Did you read the "p.s." thing? It states that the example is just to clarify my question- how to template the inherited class.
Matthew Faithfull 11-Apr-13 16:18pm    
I'm still not sure I get what you're trying to do but if you must use inheritance for some reason what is to stop you doing this:

template< class Item > class directedListTypeIter : public typename std::list<item>::iterator

This keeps the directedListTypeIter generic but doesn't deal with which type of iterator, forward or back it is. Either way you don't need to reimplement the assignment operator unless you add data members.
debil123 13-Apr-13 17:49pm    
this:

template< class Item > class directedListTypeIter : public typename std::list<item>::iterator

does define which type of iterator it is. it is forward iterator.

but- as I said, the solution you posted in the beginning can solve my issue. but I am not interested in solving this particular issue of creating forward, or reverse iterator. I am interested in finding how to template inheritance.
I mean- why this:
directedListTypeIter& operator=(realIter &constructorIter){
((realIter*)this)->operator=(constructorIter);
return *this;
}
is ambiguity?
Matthew Faithfull 13-Apr-13 19:47pm    
The simple answer is because you don't need to write this function, it already exists for the base class and given that the derived class doesn't add any data, assignment operator is the same function as that of the base class. Technically this is to do with concepts like 'type coersion', 'promotion' and 'automatic type conversion' which you can research but put simply, don't write the function, it's not needed, no longer any ambiguity.
debil123 14-Apr-13 2:45am    
it doesn't compile. assignment operator, although its trivial should be added to support the assignment needed by my begin() function.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900