I have a boost::bimap<int, boost::shared_ptr<A>>
container and want to return an iterator to the left view ensuring constness of the contents. Returning container.left.begin()
returns an ite开发者_开发技巧rator that dereferences to std::pair<int const, boost::shared_ptr<A> const>
.
Obviously, this is not what I want, since it's possible to change A
by dereferencing the shared_ptr
. I want an iterator that dereferences to std::pair<int const, boost::shared_ptr<A const>>
(I don't really care if the shared_ptr is const or not). I know I should probably be doing this with the use of boost::transform_iterator, but I can't figure out what the "casting" function should look like.
Can anybody help me out with this? Or is there another, easier method to obtain what I want?
Edit: Here's what I have so far, suffice to say, it's giving me a good 2 screens worth of errors.
typedef boost::bimap<unsigned int, boost::shared_ptr<A> > container_type;
typedef container_type::left_const_iterator base_const_iterator;
typedef boost::transform_iterator<makeIterConst<A>, base_const_iterator> const_iterator;
template <typename T>
struct makeIterConst : std::unary_function<std::pair<unsigned int const, boost::shared_ptr<T> const>, std::pair<unsigned int const, boost::shared_ptr<T const> const> >
{
std::pair<unsigned int const, boost::shared_ptr<T const> const> operator() (std::pair<int const, boost::shared_ptr<T> const> const & orig) const
{
std::pair<int const, boost::shared_ptr<T const> const> newPair(orig.first, boost::const_pointer_cast<T const>(orig.second));
return newPair;
}
};
Here's the "core" error:
note: candidate function not viable: no known conversion from 'const boost::bimaps::relation::structured_pair, boost::bimaps::tags::tagged, boost::bimaps::relation::member_at::right>, mpl_::na, boost::bimaps::relation::normal_layout>' to 'const std::pair >' for 1st argument
The problem is that your value_type
is not actually a std::pair
(and is not implicitly convertible to one), and thus cannot be passed to makeIterConst::operator()
.
Make it take const base_const_iterator::value_type &
instead.
#include <iostream>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bimap.hpp>
#include <boost/iterator/transform_iterator.hpp>
struct A
{
std::string data;
A(const std::string& s) : data(s) {}
};
typedef boost::bimap<unsigned int, boost::shared_ptr<A> > container_type;
typedef container_type::left_map::const_iterator base_const_iterator;
template <typename T>
struct makeIterConst : std::unary_function<base_const_iterator::value_type const &,
std::pair<unsigned int const, boost::shared_ptr<T const> const> >
{
std::pair<unsigned int const, boost::shared_ptr<T const> const> operator()
(base_const_iterator::value_type const & orig) const
{
std::pair<int const, boost::shared_ptr<T const> const> newPair(orig.first, boost::const_pointer_cast<T const>(orig.second));
return newPair;
}
};
typedef boost::transform_iterator<makeIterConst<A>,
base_const_iterator> const_iterator;
int main()
{
container_type m;
boost::shared_ptr<A> p = boost::make_shared<A>("foo");
m.insert( container_type::value_type(1, p));
// using regular iterator
for( base_const_iterator left_iter = m.left.begin();
left_iter != m.left.end();
++left_iter )
{
std::cout << left_iter->first << " --> " << left_iter->second->data << '\n';
left_iter->second->data = "bar"; // compiles
}
// using constified iterator
for( const_iterator left_iter = boost::make_transform_iterator(m.left.begin(), makeIterConst<A>() );
left_iter != boost::make_transform_iterator(m.left.end(), makeIterConst<A>() );
++left_iter )
{
std::cout << left_iter->first << " --> " << left_iter->second->data << '\n';
// the following will give a compilation error, as expected
// left_iter->second->data = "changed_foo";
}
}
test: https://ideone.com/fHIUe
精彩评论