std::mapやboost::unordered_mapからキーのRangeを生成するmap_keysと、
値のRangeを生成するmap_valuesですが、これらのRangeアダプタはpairのvectorなどにも適用することができます。
#include <vector> #include <utility> #include <boost/assert.hpp> #include <boost/range/adaptor/map.hpp> #include <boost/range/algorithm/equal.hpp> #include <boost/assign/list_of.hpp> int main() { const std::vector<std::pair<int, char> > v = boost::assign::list_of (std::make_pair(3, 'a')) (std::make_pair(1, 'b')) (std::make_pair(4, 'c')); { const int expected[] = {3, 1, 4}; BOOST_ASSERT(boost::equal(v | boost::adaptors::map_keys, expected)); } { const char expected[] = { 'a', 'b', 'c' }; BOOST_ASSERT(boost::equal(v | boost::adaptors::map_values, expected)); } // mutable version { std::vector<std::pair<int, char> > mv(v.begin(), v.end()); const char expected[] = { 'a', 'b', 'c' }; BOOST_ASSERT(boost::equal(mv | boost::adaptors::map_values, expected)); } }
しかし、Boost 1.43.0時点でのmap_keys, map_valuesの実装が、Rangeに対してvalue_typeを持っていることを要求しているため、配列に対して適用することができません。
// <boost/range/adaptor/map.hpp> template< class Map > struct select_first { typedef BOOST_DEDUCED_TYPENAME Map::value_type pair_t; typedef const BOOST_DEDUCED_TYPENAME pair_t::first_type& result_type; ... }; template< class Map > struct select_second_mutable { typedef BOOST_DEDUCED_TYPENAME Map::value_type pair_t; typedef BOOST_DEDUCED_TYPENAME pair_t::second_type& result_type; ... }; template< class Map > struct select_second_const { typedef BOOST_DEDUCED_TYPENAME Map::value_type pair_t; typedef const BOOST_DEDUCED_TYPENAME pair_t::second_type& result_type; ... };
これを以下のように修正すれば、配列に対しても適用できるようになります。
// <boost/range/adaptor/map.hpp> template< class Map > struct select_first { typedef BOOST_DEDUCED_TYPENAME range_value<Map>::type pair_t; typedef const BOOST_DEDUCED_TYPENAME pair_t::first_type& result_type; ... }; template< class Map > struct select_second_mutable { typedef BOOST_DEDUCED_TYPENAME range_value<Map>::type pair_t; typedef BOOST_DEDUCED_TYPENAME pair_t::second_type& result_type; ... }; template< class Map > struct select_second_const { typedef BOOST_DEDUCED_TYPENAME range_value<Map>::type pair_t; typedef const BOOST_DEDUCED_TYPENAME pair_t::second_type& result_type; ... };
以下、テストコードです。
#include <utility> #include <boost/assert.hpp> #include <boost/range/adaptor/map.hpp> #include <boost/range/algorithm/equal.hpp> #include <boost/range/algorithm/copy.hpp> int main() { const std::pair<int, char> ar[] = { std::make_pair(3, 'a'), std::make_pair(1, 'b'), std::make_pair(4, 'c') }; { const int expected[] = {3, 1, 4}; BOOST_ASSERT(boost::equal(ar | boost::adaptors::map_keys, expected)); } { const char expected[] = { 'a', 'b', 'c' }; BOOST_ASSERT(boost::equal(ar | boost::adaptors::map_values, expected)); } // mutable version { std::pair<int, char> mar[3]; boost::copy(ar, boost::begin(mar)); const char expected[] = { 'a', 'b', 'c' }; BOOST_ASSERT(boost::equal(mar | boost::adaptors::map_values, expected)); } }
これはバグだと思われるので、不具合報告(パッチ付き)しておきました。
https://svn.boost.org/trac/boost/ticket/4388