error: no match for 'operator[]' in... <near match> - c++

This fail to compile in gcc 4.1.2 / RedHat 5 :
#include <string>
#include <vector>
#include <map>
class Toto {
public:
typedef std::string SegmentName;
};
class Titi {
public:
typedef Toto::SegmentName SegmentName; // import this type in our name space
typedef std::vector<SegmentName> SegmentNameList;
SegmentNameList segmentNames_;
typedef std::map<SegmentName, int> SegmentTypeContainer;
SegmentTypeContainer segmentTypes_;
int getNthSegmentType(unsigned int i) const {
int result = -1;
if(i < segmentNames_.size())
{
SegmentName name = segmentNames_[i];
result = segmentTypes_[ name ];
}
return result;
}
};
The error is :
error: no match for 'operator[]' in '(...)segmentTypes_[name]'
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:340:
note: candidates are: _Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&)
[with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = int, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> >]
Why ? The map is rather straightforward. I guess this has to do with the typedefs, but what is wrong ?
[edit] Even if I remove all the typedefs and use std::string everywhere, the problem persists... Am I misusing maps ?

std::map::operator[] is non-const and you're trying to use it from a const method.
You could achieve this using std::map::find, which returns a const_iterator:
SegmentTypeContainer::const_iterator iter = segmentTypes_.find(name);
If you're using C++11, you could also use std::map::at, which will throw an exception if the key is not found in the map:
result = segmentTypes_.at(name);

std::map::operator[] is not a const method, but you are calling it from a const method of your class. The reason for this is that it adds an element if the key is not present.
You can use C++11 at():
result = segmentTypes_.at(name); // throws exception if key not present.
or use std::map::find.
SegmentTypeContainer::const_iterator it = segmentTypes_.find(name);
if (it != segmentTypes_.end())
{
// OK, element with key name is present
result = it->second;
}

Related

Is Adding boost::any in a boost::property_tree Possible?

I am trying to store a boost::any type to a boost property tree. Here is some runnable example:
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <sys/types.h>
#include <boost/any.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
int main()
{
boost::property_tree::ptree pTree_Root;
pTree_Root.put("sigRoot.property1", "value1");
pTree_Root.put("sigRoot.property2", "value2");
pTree_Root.put("sigRoot.property3", "value3");
std::vector<std::string> vecString;
for(int i = 0; i <= 5; i++) {
vecString.push_back("somestring");
}
boost::any anyVar = vecString;
pTree_Root.put("sigRoot.property4", anyVar);
std::stringstream ss;
boost::property_tree::json_parser::write_json(ss, pTree_Root);
std::string jsonString = ss.str();
jsonString.erase(std::remove(jsonString.begin(), jsonString.end(), '\n'), jsonString.end());
std::cout << jsonString << std::endl;
return 0;
}
This does not work, probably for the same reason boost::any is not serializable. But I see I am allowed to query anyVar.type(), but I have no idea what can be done with it. Is it possible to somehow use auto or something else to add the data to the property tree without explicitly coding a fixed number of known types here? C++11/C++0x methods are also welcome.
This is the error I get:
In file included from /usr/include/boost/property_tree/ptree.hpp:17:0,
from pTreeTest.cpp:8:
/usr/include/boost/property_tree/stream_translator.hpp: In static member function ‘static void boost::property_tree::customize_stream<Ch, Traits, E, Enabler>::insert(std::basic_ostream<_Ch, _Tr>&, const E&) [with Ch = char, Traits = std::char_traits<char>, E = boost::any, Enabler = void]’:
/usr/include/boost/property_tree/stream_translator.hpp:199:13: instantiated from ‘boost::optional<std::basic_string<Ch, Traits, Alloc> > boost::property_tree::stream_translator<Ch, Traits, Alloc, E>::put_value(const E&) [with Ch = char, Traits = std::char_traits<char>, Alloc = std::allocator<char>, E = boost::any]’
/usr/include/boost/property_tree/detail/ptree_implementation.hpp:795:54: instantiated from ‘void boost::property_tree::basic_ptree<Key, Data, KeyCompare>::put_value(const Type&, Translator) [with Type = boost::any, Translator = boost::property_tree::stream_translator<char, std::char_traits<char>, std::allocator<char>, boost::any>, Key = std::basic_string<char>, Data = std::basic_string<char>, KeyCompare = std::less<std::basic_string<char> >]’
/usr/include/boost/property_tree/detail/ptree_implementation.hpp:817:13: instantiated from ‘boost::property_tree::basic_ptree<K, D, C>& boost::property_tree::basic_ptree<Key, Data, KeyCompare>::put(const path_type&, const Type&, Translator) [with Type = boost::any, Translator = boost::property_tree::stream_translator<char, std::char_traits<char>, std::allocator<char>, boost::any>, Key = std::basic_string<char>, Data = std::basic_string<char>, KeyCompare = std::less<std::basic_string<char> >, boost::property_tree::basic_ptree<Key, Data, KeyCompare>::path_type = boost::property_tree::string_path<std::basic_string<char>, boost::property_tree::id_translator<std::basic_string<char> > >]’
/usr/include/boost/property_tree/detail/ptree_implementation.hpp:832:72: instantiated from ‘boost::property_tree::basic_ptree<K, D, C>& boost::property_tree::basic_ptree<Key, Data, KeyCompare>::put(const path_type&, const Type&) [with Type = boost::any, Key = std::basic_string<char>, Data = std::basic_string<char>, KeyCompare = std::less<std::basic_string<char> >, boost::property_tree::basic_ptree<Key, Data, KeyCompare>::path_type = boost::property_tree::string_path<std::basic_string<char>, boost::property_tree::id_translator<std::basic_string<char> > >]’
pTreeTest.cpp:26:47: instantiated from here
/usr/include/boost/property_tree/stream_translator.hpp:33:13: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
/usr/include/c++/4.6/ostream:581:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char, _Traits = std::char_traits<char>, _Tp = boost::any]’
No. boost::any has no operator <<. You cannot use any in property_tree. anyVar.type() returns std::typeinfo, this class provides runtime information about type.
template<typename Type, typename Translator>
self_type & put(const path_type & path, const Type & value, Translator tr);
Set the value of the node at the given path to the supplied value, translated to the tree's data type. If the node doesn't exist, it is created, including all its missing parents.
You can create Translator and pass it to function put, since ptree is really basic_ptree<std::string, std::string> your translator should convert your any to string.
Simple example of translator
struct SimpleTranslator
{
public:
boost::optional<std::string> put_value(const boost::any& value)
{
if (value.type() == typeid(std::vector<std::string>))
{
std::stringstream ss;
std::vector<std::string> vec = boost::any_cast<std::vector<std::string>>(value);
std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(ss));
return ss.str();
}
return boost::optional<std::string>();
}
};
http://liveworkspace.org/code/275820c1becfb63deda4e4eed8524833

= not defined for std::search when using const string&

I have the following code, which works fine, however when I change the iter getB(string& s , string& tag); function definition to iter getB(const string& s , const string& tag); I get the error pasted at the end. I believe the = operator is not defined because with this new function definition, if I don't assign the result of search to i the program compiles, though later resulting in a segmentation fault, which I believe is expected. Can someone explain to me why I can't assign the result of search when the function definition contains const keywords. Thank you.
the code:
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
typedef string::iterator iter;
iter getB(string& s , string& tag);
int main (){
string line = "hello, how are you?";
string tag = "how";
iter i = getB(line,tag);
for(i ; i!=line.end(); i++){
cout << *i ;
}
cout << endl;
return 0;
}
iter getB(string& s , string& tag)
{
iter i;
i = search(s.begin() , s.end() , tag.begin() , tag.end());
return i;
}
~
~
the error message with the altered function definition:
test1.cpp: In function ‘iter getB(const std::string&, const std::string&)’:
test1.cpp:24: error: no match for ‘operator=’ in ‘i = std::search [with _ForwardIterator1 = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _ForwardIterator2 = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >](((const std::string*)s)->std::basic_string<_CharT, _Traits, _Alloc>::begin [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>](), ((const std::string*)s)->std::basic_string<_CharT, _Traits, _Alloc>::end [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>](), ((const std::string*)tag)->std::basic_string<_CharT, _Traits, _Alloc>::begin [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>](), ((const std::string*)tag)->std::basic_string<_CharT, _Traits, _Alloc>::end [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]())’
/usr/include/c++/4.2.1/bits/stl_iterator.h:637: note: candidates are: __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >& __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator=(const __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)
For a const string, begin() and end() return std::string::const_iterator not std::string::iterator. You can convert an iterator to a const_iterator, but not vice versa.
The quick solution would be to change your typedef:
typedef string::const_iterator iter;
If s is a const string &, then s.begin(), and hence the return type of search, is string::const_iterator. This is not convertible to string::iterator, which is the type of i.
This is as it should be, since otherwise that conversion would break const-correctness by allowing you to modify the string. You should change the type of i to string::const_iterator, or perhaps auto if you're using C++11.
if you pass in a const iterator to std::search, then the return value is also a const iterator (it will be of the same type as the first iterator passed in)
change this:
typedef string::iterator iter;
to this:
typedef string::const_iterator iter;

"No match for operator=" trying to iterate through map in C++

I'm trying to iterate through a map defined as the following:
std::map< size_type, std::pair<size_t, unsigned int> > ridx_;
Now I'm trying to iterate through ridx_ (which is a private member of a class) in the following friend function which overloads operator<<
std::ostream& operator<<(std::ostream &os, const SMatrix &m)
{
std::map< size_type, std::pair<size_t, unsigned int> >::iterator it;
//The following is line 34
for (it = m.ridx_.begin(); it != m.ridx_.end(); it++)
os << it->first << endl;
return os;
}
However g++ errors out with:
SMatrix.cpp:34: error: no match for 'operator=' in 'it =
m->SMatrix::ridx_.std::map<_Key, _Tp, _Compare, _Alloc>::begin with
_Key = unsigned int, _Tp = std::pair,
_Compare = std::less, _Alloc =
std::allocator > >' /usr/include/c++/4.3/bits/stl_tree.h:152: note:
candidates are: std::_Rb_tree_iterator > >&
std::_Rb_tree_iterator > >::operator=(const
std::_Rb_tree_iterator > >&) make: * [myTest] Error 1
What am I doing wrong?
Because m (and therefore m.ridx_) is const, you must use the std::map< size_type, std::pair<size_t, unsigned int> >::const_iterator, not ::iterator here.
If you're using a C++0x compiler, you might want to consider using auto as well:
for (auto it = m.ridx_.begin(); it != m.ridx_.end(); it++)

error: invalid use of 'Config::testMap'

Here is the code:
#include <iostream>
#include <string>
#include <map>
#include <stdexcept>
#include <boost/ptr_container/ptr_vector.hpp>
struct TestStruct
{
std::string str1;
int var1;
};
struct Config
{
// Map
typedef std::map< std::string, boost::ptr_vector<struct TestStruct> > testMap;
};
void foo(Config& config)
{
if (config.testMap.empty())
{
std::cout << "It worked!" << std::endl;
}
else
{
std::cout << "It didn't work!" << std::endl;
}
return;
}
int testMain(void)
{
Config config;
foo(config);
return;
}
int main(void)
{
try
{
return testMain(/*argc, argv*/);
}
catch(std::exception& err)
{
std::cerr << "Error running program: " << err.what() << std::endl;
return 1;
}
catch(...)
{
std::cerr << "Program failed with an unknown exception." << std::endl;
return 1;
}
}
I'm new to maps - never used one before. I've found many examples of how to use them online. Unfortunately I can't seem to makes sense of more advanced examples of them.
What I'd like to do is create a map with a key (std::string) and a value (boost::ptr_vector<struct>).
I was going to start by just declaring and passing it around successfully. Then I wanted try and figure out how to fill it up.
I ran into an error that is just vague enough I don't know how to interpret it.
Any suggestions on what I've done wrong in the "use" of testMap?
Also, can someone provide some simple example of how I can populate the map up.
Say I want a key of a and a value of str1 = "hello", var1 = 10. How would I do this?
FOLLOW UP QUESTION:
In regards to the answer left below by Kerrek SB.
If I do the following...
std::string key = "a";
TestStruct value = {"hello", 10};
config.testMap[key] = value;
I get the following error:
error: no match for 'operator=' in 'config->Config::testMap.std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> > > >](((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >*)(& key)))) = value'
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note: candidates are: boost::ptr_vector<T, CloneAllocator, Allocator>& boost::ptr_vector<T, CloneAllocator, Allocator>::operator=(std::auto_ptr<boost::ptr_vector<T, CloneAllocator, Allocator> >) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note: boost::ptr_vector<T, CloneAllocator, Allocator>& boost::ptr_vector<T, CloneAllocator, Allocator>::operator=(boost::ptr_vector<T, CloneAllocator, Allocator>) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
If instead I do the .insert() method I get the following error:
instantiated from here
/opt/csw/gcc4/lib/gcc/sparc-sun-solaris2.8/4.3.2/../../../../include/c++/4.3.2/bits/stl_pair.h:106: error: no matching function for call to 'boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >::ptr_vector(const TestStruct&)'
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:50: note: candidates are: boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector(typename boost::ptr_sequence_adapter<T, std::vector<void*, Allocator>, CloneAllocator>::size_type, const typename boost::ptr_sequence_adapter<T, std::vector<void*, Allocator>, CloneAllocator>::allocator_type&) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note: boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector(std::auto_ptr<boost::ptr_vector<T, CloneAllocator, Allocator> >) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note: boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector(const typename boost::ptr_sequence_adapter<T, std::vector<void*, Allocator>, CloneAllocator>::allocator_type&) [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:45: note: boost::ptr_vector<T, CloneAllocator, Allocator>::ptr_vector() [with T = TestStruct, CloneAllocator = boost::heap_clone_allocator, Allocator = std::allocator<void*>]
/usr/local/boost/boost_1_38_0_gcc4/include/boost/ptr_container/ptr_vector.hpp:35: note: boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >::ptr_vector(const boost::ptr_vector<TestStruct, boost::heap_clone_allocator, std::allocator<void*> >&)
FOLLOW UP:
From what I've researched this is not possible.
You cannot use a ptr_vector in a map. (so I've been told) Due to ownership/copy issues?
"What happens when you attempt to copy a ptr_vector, which is bound to happen inside a map? The pointer containers model exclusive ownership of pointers.
You can do this with C++0x and std::move, but that won’t help you here."
Can anyone provide a counter example?
Your class Config doesn't contain any members! (Just a typedef.) Define a member, too:
struct Config
{
typedef std::map<std::string, boost::ptr_vector<TestStruct> > testMap_type;
testMap_type testMap; // member
};
Also, in C++ there is no need to say struct TestStruct, just say TestStruct.
To add an element:
std::string key = "xxx";
TestStruct val = { "hello", 10 };
// Insert with []-operator
config.testMap[key] = val;
// Insert with insert():
config.testMap.insert(std::pair<std::string, TestStruct>(key, val)); // alternative
Edit: Sorry, I misrepresented your actual data structure. Here's an example with a std::vector:
typedef std::map<std::string, std::vector<int>> MyMap;
MyMap m;
m["hello"].push_back(1);
m["hello"].push_back(2);
m["world"].push_back(3);
In your case, you could say config.testMap[key].push_back(val), or you could make a new vector:
boost::ptr_vector<TestStruct> new_v;
// populate new_v;
config.testMap.insert(std::pair<std::string, boost::ptr_vector<TestStruct>>(key, new_v);
From what I've researched this is not possible.
You cannot use a ptr_vector in a map. (so I've been told) Due to ownership/copy issues?
"What happens when you attempt to copy a ptr_vector, which is bound to happen inside a map? The pointer containers model exclusive ownership of pointers.
You can do this with C++0x and std::move, but that won’t help you here."

Is it possible to use STL copy function with map

I wonder if there is any trick to use copy with maps to copy the contents of map into an array. Because STL maps are by the combination of a key value and a mapped value an element of a map forms a key value pair. That prevents us to use standard algorithms like std::copy. For example following code gives error:
#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;
}
Error:
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
Is there any easy trick/hack to overcome this problem.
Disclaimer: Not interested in solutions that iterates over map in a for loop and adds elements to the array.
You could use std::transform instead:
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>);
And as #Andre points out in a comment below, if you want a slightly more verbose overhead, you can avoid having to explicitly state the template arguments via a functor:
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());
I'm sure there's a less-verbose solution using Boost binders, but I can't remember the syntax off the top of my head.
Ewww, malloc? Anyway, if you want to copy a map, you have to remember the keys too.
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;
}
If you consider std::map an STL container, then it is a container of
std::pair<key_type, mapped_type>. (This is what its value_type is
defined to be, and it is designed so that it can be used as a
container.) If you want simply one part of it, the correct function is
std::transform, with a transformation function which maps the
value_type to either the key_type or the mapped_type. (If you make
much use of std::pair—or std::map, whose value_type is an
std::pair, you should probably have functional objects for this in
your tool kit:
struct ExtractFirst
{
template<typename Pair>
typename boost::remove_const<typename Pair::first_type>::type
operator()( Pair const& from ) const
{
return from.first;
}
};
, and the same thing for ExtractSecond.
Your target would be an arraystd::vector[please!] of std::pair<int,double> objects unless, yes, you unroll it yourself.
(You could create your own InputIterator as a proxy, or play with std::transform and a std::back_inserter, but that's just being silly. You'll make your code far more verbose than just looping through the map.)
The simplest way is to use std::transform in combination with boost::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 ) );
If you could use C++0x (without 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 ); } );