Примечание: Я написал «рецепт» на основе уроков, извлеченных из учений и ответы & комментарии на этой странице, см http://www.codeproject.com/Tips/1029941/Python-like-enumeration-in-Cplusplus.шаблон для сопзЬ итератор вместо итератора
Я играю с расширениями, которые C++ 11 приносит на C++ 03. Я хочу, чтобы иметь возможность перебирать контейнер, используя следующий код:
int main()
{
std::list<int> list = { 1, 2, 3, 4, 5, 6, 7 };
for (auto x : enumerated(list))
cout << x.first << " " << x.second << endl;
for (auto x : const_enumerated(list))
cout << x.first << " " << x.second << endl;
}
Первая итерация имеет изменяемую х, против для второй, пытаясь изменить х приведет к ошибке компиляции. У меня есть то, что работает для неконстантного случая:
template <typename Container>
class EnumerationAdaptor
{
public:
EnumerationAdaptor(Container& container) : container_(container) {}
EnumIter<typename Container::iterator> begin() const { return container_.begin(); }
EnumIter<typename Container::iterator> end() const { return container_.end(); }
private:
Container& container_;
};
template <typename Container>
EnumerationAdaptor<Container> enumerated(Container& container) { return container; }
template <typename Container>
EnumerationAdaptor<const Container> const_enumerated(const Container& container) { return container; }
неконстантная случае использует EnumIter<std::list<...>::iterator>
, как хотелось бы, и я пытаюсь сделать сопзЬ случай использовать EnumIter<std::list<...>::const_iterator>
в качестве возвращаемого типа begin()
и end()
. Похоже, мне нужно decltype:
template <typename Container>
class EnumerationAdaptor
{
public:
EnumerationAdaptor(Container& container) : container_(container) {}
EnumIter<decltype(Container().begin())> begin() const { return container_.begin(); }
EnumIter<decltype(Container().end())> end() const { return container_.end(); } // *** compile error (see below)
private:
Container& container_;
};
Но я получаю ошибку компиляции в Visual Studio 2015 Экспресс:
Error C2440 'return': cannot convert from
'std::_List_const_iterator<std::_List_val<std::_List_simple_types<int>>>'
to
'EnumIter<std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>>'
[in c:\users\...\enumeratedcpp.cpp line 46, which is line marked ***]
, который говорит о том, что я делаю что-то неправильно с decltype, как компилятор отыскания non-const begin(). Есть ли способ исправить это?
EDIT: даже с простой EnumIter, проблема в том же:
template <typename Iter>
class EnumIter
{
public:
EnumIter(Iter begin) : iter_(begin) {}
EnumIter& operator++()
{
return *this;
}
bool operator!=(const EnumIter& rhs)
{
return iter_ != rhs.iter_; // or self.index_ != rhs.index_;
}
int operator*() const
{
return index_;
}
private:
Iter iter_;
int index_ = 0;
};
это, вероятно, проще решить с помощью отдельного 'ConstEnumerationAdaptor', который вызывает' cbegin' и 'cend' – sp2danny
в противном случае, попробуйте заменить' Container() '(внутри decltype) на' std :: declval() '(from ) –
sp2danny
На самом деле, я думаю, что проблема может заключаться в 'EnumIter <>' – sp2danny