7 Stimmen

Benutzerdefinierter Iterator funktioniert nicht mit BOOST_FOREACH?

Ich habe eine Klasse, die einige Daten enthält, und ich würde gerne hinzufügen begin() y end() Funktionen, die Iteratoren über die IDs der Daten bereitstellen.

Ich verwende den Boost counting_iterator :

#include <iostream>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/iterator/counting_iterator.hpp>

template<class T>   
class ContainerTpl {
 public:
  typedef std::size_t Id;
  typedef boost::counting_iterator<Id> const_iterator;
  ContainerTpl() {}
  const_iterator begin() {
    return boost::counting_iterator<Id>(0);
  }
  const_iterator end() {
    return boost::counting_iterator<Id>(container_.size());
  }
 private:
  std::vector<T> container_;
};

int main () {
  typedef ContainerTpl<double> Container;
  Container c;
  BOOST_FOREACH (Container::Id cid, c) {
    std::cerr << cid << std::endl;
  }
  return 0;
}

Bitte beachten Sie, dass es sich hierbei um minimalen Beispielcode handelt; in Wirklichkeit enthält die Klasse mehr Funktionalität, so dass z. B. eine typedef a vector wäre nicht ausreichend. Ich brauche diese Klasse wirklich, mit einem Iterator über IDs.

Leider gibt mir der obige Code ziemlich üble Compilerfehler:

In file included from boost/foreach.hpp:71,
                 from a.cpp:3:
boost/mpl/eval_if.hpp: In instantiation of ‘boost::mpl::eval_if<mpl_::bool_<false>, boost::range_const_iterator<ContainerTpl<double> >, boost::range_mutable_iterator<ContainerTpl<double> > >’:
boost/foreach.hpp:355:   instantiated from ‘boost::foreach_detail_::foreach_iterator<ContainerTpl<double>, mpl_::bool_<false> >’
a.cpp:25:   instantiated from here
boost/mpl/eval_if.hpp:38: error: no type named ‘type’ in ‘struct boost::range_mutable_iterator<ContainerTpl<double> >’
a.cpp: In function ‘int main()’:
a.cpp:25: error: no matching function for call to ‘begin(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<ContainerTpl<double>, mpl_::bool_<false> >*, boost::mpl::o\
r_<boost::mpl::and_<boost::mpl::not_<boost::is_array<ContainerTpl<double> > >, mpl_::bool_<false>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, boost::mpl::and_<boost::mpl::not_<boo\
st::foreach::is_noncopyable<ContainerTpl<double> > >, boost::foreach::is_lightweight_proxy<ContainerTpl<double> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, mpl_::bool_<false>, m\
pl_::bool_<false>, mpl_::bool_<false> >*)’
a.cpp:25: error: no matching function for call to ‘end(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<ContainerTpl<double>, mpl_::bool_<false> >*, boost::mpl::or_\
<boost::mpl::and_<boost::mpl::not_<boost::is_array<ContainerTpl<double> > >, mpl_::bool_<false>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, boost::mpl::and_<boost::mpl::not_<boost\
::foreach::is_noncopyable<ContainerTpl<double> > >, boost::foreach::is_lightweight_proxy<ContainerTpl<double> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, mpl_::bool_<false>, mpl\
_::bool_<false>, mpl_::bool_<false> >*)’
a.cpp:25: error: no matching function for call to ‘deref(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<ContainerTpl<double>, mpl_::bool_<false> >*)’

Wie kann ich den Code zum Laufen bringen?

UPDATE: Nach der Antwort füge ich den folgenden Code hinzu, mit dem es funktioniert:

namespace boost
{
// specialize range_mutable_iterator and range_const_iterator in                                                                                                                                    
// namespace boost                                                                                                                                                                                  
template<class T>
struct range_mutable_iterator< ContainerTpl<T> > {
  typedef typename ContainerTpl<T>::const_iterator type;
};

template<class T>
struct range_const_iterator< ContainerTpl<T> > {
  typedef typename ContainerTpl<T>::const_iterator type;
};
} // end namespace

8voto

Tim Sylvester Punkte 22343

In den Boost-Dokumenten gibt es dazu eine Seite:

http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/foreach/extensibility.html

Kurz gesagt, Sie müssen Folgendes definieren boost::range_mutable_iterator<> für Ihren Typ, damit der Compiler den Vorlagentyp instanziieren kann, der BOOST_FOREACH zu verwenden versucht.

edit für zukünftige Googler:

Ich bin mir nicht sicher, ob diese "Sandbox"-URL immer auf die neueste Version verweist oder ob es sich um einen vorübergehenden Ort handelt, der irgendwann nicht mehr funktioniert. Dies ist der Link für die aktuelle Version, die stabiler sein könnte, obwohl sie veraltet sein wird:

http://www.boost.org/doc/libs/1_50_0/doc/html/foreach/extensibility.html

2voto

Gustey Punkte 21

Ich weiß, dass diese Frage alt ist, aber sie scheint immer noch relevant zu sein. Ich hatte dieses Problem und bemerkte, dass boost foreach erfordert, dass Sie einen veränderbaren Iterator sowie eine const_iterator definiert haben (also sowohl ContainerTpl::Iterator und ContainerTpl::const_iterator). Wenn das nicht der Fall ist, müssen Sie den Anweisungen von Tim folgen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X