Search code examples
c++iteratorgeneric-programming

Generic iterator/pointer initialization


I have a C++ class Finder that stores a location in containers plus some additional data. Such containers have the type std::string but also char * or MyString. Say, the class looks like this (Iterator<TContainer>::Type is a trait / metafunction that returns the iterator type for a given container):

template <typename TContainer>
class Finder
{
public:
  typedef typename Iterator<TContainer>::Type TIterator;
  TIterator iterator;

  // Initialization of iterator: How to do it generically?

  // Finder {}                       // problem with pointers!
  // Finder() : iterator(0) {}       // problem with iterators!
};

The main problem now is how to initialize the iterator that can be a pointer or an iterator. If I only wanted to support my own containers then I could simply implement a constructor that takes nullptr_t following the nullptr idiom. However, since I want to support pointers, my own iterators and STL iterators, I'm a bit out of depth here.

The best thing that I can imagine is to write a getNil<>() function, e.g. the code below. However, now at least three questions arise:

  1. Is this the best way to achieve my aim?

  2. How to determine whether a type is a STL iterator? I would probably need some #ifs, and tailor code to each compiler/STL version to use.

  3. Is it possible at all to get a nil iterator in the STL? Is the result of x-y in std::vector<int> x, y; int x = x-y; defined at all?

The code:

// Forward declaration.
template <typename T>
T getNil<T>();

template <typename TValue> TValue * getNil<TValue *>()
{ return NULL; }

template <typename TValue> TValue * const getNil<TValue * const>()
{ return NULL; }

template <> TValue * const getNil<MyIterator>()
{ return MyIterator(nullptr); }  // nullptr from above idiom

template <> TStlIterator
boost::enable_if<
    MagicallyDetermineIfIsStlIterator<TStlIterator>::value,
    TStlIterator>
getNil<TStlIterator>()
{ return MyIterator(nullptr); }  // nullptr from above idiom

Solution

  • Finder() : iterator() { }
    

    Should do the trick. Not providing an argument for a member in the initialization list will call the default constructor on a type that has one, and will zero-initialize POD types including pointers (and it will fail if the type has no default constructor, but that seems unlikely given your scenario).