是否可以使用STL复制功能与地图

时间:2011-06-01 11:06:55

标签: c++ stl map copy

我想知道是否有任何技巧可以使用地图复制将地图内容复制到数组中。因为STL映射是通过键值和映射值的组合,所以映射的元素形成键值对。这阻止我们使用标准算法,如std :: copy。例如,以下代码给出了错误:

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

int
main()
{
  std::map <int, double> test(4);
  test[0] = 11;
  test[2] = 1.23;
  test[3] = 23.29;
  test[1] = 12.12;
  double *test_arr = (double *) malloc(4 * sizeof(double));
  std::copy(test.begin(), test.end(), test_arr);
  std::cout << test_arr[3] << std::endl;
  return 0;
}

错误:

stl_copy_tests.cpp: In function ‘int main()’:
stl_copy_tests.cpp:9:32: error: no matching function for call to ‘std::map<int, double>::map(int)’
/usr/include/c++/4.5/bits/stl_map.h:170:7: note: candidates are: std::map<_Key, _Tp, _Compare, _Alloc>::map(const std::map<_Key, _Tp, _Compare, _Alloc>&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, std::map<_Key, _Tp, _Compare, _Alloc> = std::map<int, double>]
/usr/include/c++/4.5/bits/stl_map.h:159:7: note:                 std::map<_Key, _Tp, _Compare, _Alloc>::map(const _Compare&, const allocator_type&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, allocator_type = std::allocator<std::pair<const int, double> >]
/usr/include/c++/4.5/bits/stl_map.h:150:7: note:                 std::map<_Key, _Tp, _Compare, _Alloc>::map() [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >]
In file included from /usr/include/c++/4.5/bits/char_traits.h:41:0,
                 from /usr/include/c++/4.5/ios:41,
                 from /usr/include/c++/4.5/ostream:40,
                 from /usr/include/c++/4.5/iostream:40,
                 from stl_copy_tests.cpp:1:
/usr/include/c++/4.5/bits/stl_algobase.h: In static member function ‘static _OI std::__copy_move<<anonymous>, <anonymous>, <template-parameter-1-3> >::__copy_m(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*, bool <anonymous> = false, bool <anonymous> = false, <template-parameter-1-3> = std::bidirectional_iterator_tag]’:
/usr/include/c++/4.5/bits/stl_algobase.h:404:70:   instantiated from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
/usr/include/c++/4.5/bits/stl_algobase.h:442:39:   instantiated from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
/usr/include/c++/4.5/bits/stl_algobase.h:474:18:   instantiated from ‘_OI std::copy(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’
stl_copy_tests.cpp:15:47:   instantiated from here
/usr/include/c++/4.5/bits/stl_algobase.h:319:6: error: cannot convert ‘std::pair<const int, double>’ to ‘double’ in assignment

是否有任何简单的技巧/黑客来克服这个问题。

免责声明:对于在for循环中迭代map并将元素添加到数组的解决方案不感兴趣。

5 个答案:

答案 0 :(得分:5)

您可以改为使用std::transform

template <typename T, typename U>
const U &extract_second(const std::pair<T,U> &p)
{
    return p.second;
}

std::transform(test.begin(), test.end(), test_arr, extract_second<int,double>);

正如@Andre在下面的评论中指出的那样,如果你想要稍微冗长的开销,你可以避免必须通过仿函数明确说明模板参数:

struct extract_second
{
    template <typename T, typename U>
    const U operator() (const std::pair<T,U> &p) const
    {
        return p.second;
    }
};

std::transform(test.begin(), test.end(), test_arr, extract_second());

我确信使用Boost活页夹有一个不那么冗长的解决方案,但我不记得我头脑中的语法。

答案 1 :(得分:4)

Ewww,malloc?无论如何,如果你想复制一张地图,你也必须记住这些关键。

int main()
{
    std::map <int, double> test(4);
    test[0] = 11;
    test[2] = 1.23;
    test[3] = 23.29;
    test[1] = 12.12;
    std::vector<std::pair<int, double>> test_arr(test.size());
    std::copy(test.begin(), test.end(), test_arr.begin());
    std::cout << test_arr[3] << std::endl;
    return 0;
}

答案 2 :(得分:2)

你的目标是std::vector对象的数组 std::pair<int,double> [please!] ,除非是的,你自己展开它。

(您可以创建自己的InputIterator作为代理,或者使用std::transformstd::back_inserter进行游戏,但这只是愚蠢的。您可以使代码更远比在地图上循环更详细。)

答案 3 :(得分:2)

如果你认为std::map是一个STL容器,那么它就是一个容器 std::pair<key_type, mapped_type>。 (这就是它的value_type 定义为,它被设计为可以用作 容器。)如果你只需要它的一部分,那么正确的功能就是 std::transform,带有映射的转换函数 value_typekey_type mapped_typestd::pair。 (如果你做的话 大量使用std::map - 或value_type,其std::pair是一个 struct ExtractFirst { template<typename Pair> typename boost::remove_const<typename Pair::first_type>::type operator()( Pair const& from ) const { return from.first; } }; ,你应该有这个功能对象 你的工具包:

ExtractSecond

,与{{1}}相同。

答案 4 :(得分:2)

最简单的方法是将std::transformboost::bind结合使用:

typedef std::map<int, double> map_t;
map_t mm;

// add elements to mm
// ...

// copy
typedef std::vector<double> vec_t;
vec_t vv;
vv.reserve( mm.size() );
std::transform( mm.begin(), mm.end(), std::back_inserter(vv), 
  boost::bind( &map_t::value_type::second, _1 ) );

如果你可以使用C ++ 0x(没有boost):

std::transform( mm.begin(), mm.end(), back_inserter(vv), 
  [](map_t::value_type val) -> double { return val.second; } );
// or
std::for_each( mm.begin(), mm.end(), 
  [&vv](map_t::value_type val) { vv.push_back( val.second ); } );