У меня есть класс C ++ Finder
, который хранит местоположение в контейнерах плюс некоторые дополнительные данные.Такие контейнеры имеют тип std::string
, но также char *
или MyString
.Скажем, класс выглядит следующим образом (Iterator<TContainer>::Type
- это признак / мета-функция, которая возвращает тип итератора для данного контейнера):
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!
};
Теперь главная проблема заключается в том, как инициализировать итератор, который может бытьуказатель или итератор.Если бы я только хотел поддерживать свои собственные контейнеры, то я мог бы просто реализовать конструктор, который принимает nullptr_t
после идиома nullptr .Однако, так как я хочу поддерживать указатели, мои собственные итераторы и STL, я немного не в этом разбираюсь.
Лучшее, что я могу себе представить, это написать getNil<>()
функция, например код ниже.Однако теперь возникает как минимум три вопроса:
Является ли это наилучшим способом достижения моей цели?
Как определить, является ли типSTL итератор?Возможно, мне понадобится #if
s и индивидуальный код для каждой версии компилятора / STL.
Возможно ли вообще получить nil итераторв STL?Определен ли результат x-y
в std::vector<int> x, y; int x = x-y;
вообще?
Код:
// 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