I am trying to learn boost mpl, tried a very simple example to count the number of times a type appears in mpl map. Could somebody explain why the output of this program is 0
typedef map<
pair<int, unsigned>
, pair<char, unsigned char>
, pair<long_<5>, char[17]>
, pair<int[42], bool>
> m;
std::cout << mpl::count <
m,
mpl::key_type
<
m,
pair<int, unsigned>
>::type
>::type::value << std::endl;
According to what is written in the code you'd like to count the occurrences of type
key_type<
m,
pair<int, unsigned>
>::type
in your map. In the end this is an int because in the description of mpl::key_type you'll find:
key_type<m,x>::type Identical to x::first;
Well, so let's see what are the actual contents of your map.
I could just write the type of the map, but I'd like to show you how to check a type the quick and lazy way. :P
So, we just make the compiler fail to see whats the type of the map.
I did it with adding this line somewhere:
typename m::blaa BB;
The compilation of course fails (because blaa is not an element of the mpl::map type) with following error message:
error: 'blaa' in 'm {aka struct boost::mpl::map<boost::mpl::pair<int, unsigned int>, boost::mpl::pair<char, unsigned char>, boost::mpl::pair<mpl_::long_<5l>, char [17]>, boost::mpl::pair<int [42], bool> >}' does not name a type
Ok, what we can read is that the map contains a list of pairs (e.g., boost::mpl::pair<int, unsigned int>),
but no int. And in your mpl::count call you are looking for int.
Just try to replace your std::cout lines with
the following lines and you'll see that the result will be as expected.
std::cout <<
boost::mpl::count< m,
boost::mpl::pair<int, unsigned>
>::type::value
<< std::endl;
Related
I am using map to store elements and I need to allocate a dynamic map memory such that I can pass this memory to caller function without any hassle however the following code snippet is confusing me. Have a look here.
std :: map <int, int> map1;
map1[some_integer_x] = some_integer_y; // OK at compilation.
But following snippet is not OK and gives error.
std :: map <int, int> * map2 = new std :: map <int, int>
map2[some_integer_x] = some_integer_y; // Not OK at compilation.
Here is the error it gives me on GCC 5.
error: no match for ‘operator=’ (operand types are ‘std::map<int, int>’ and ‘int’)
map2[some_integer_x] = some_integer_y;
I can understand that this is related to some pointers issue. What can be reason? What are my other options? I want to pass map without involving a copy as map will contain huge amount of information.
map2 is a pointer to map.
To access the std::map::operator[] you need to dereference the pointer first, using the operator *.
Because [] has higher operator precedence than *, you need to write
(*map2)[some_integer_x] = some_integer_y;
Since map2 is a pointer, then operator[] works the same way as for an array of std::map<int, int>.
The line :
map2[some_integer_x] = some_integer_y;
Means "go to the element some_integer_x and assign the to it value some_integer_y".
That causes the compilation error of mismatched type, because
type of map2[some_integer_x] is std::map<int, int> you are trying to assign an integer value to it.
So, the first of all you need to deference the pointer:
(*map2)[some_integer_x] = some_integer_y;
You are operating on the pointer to a map as if it were an instance of a map. You need to dereference the pointer before use like in the example below:
#include <map>
#include <iostream>
int main() {
std :: map <int, int> map1;
map1[1] = 2;
std::map<int, int> *map2 = new std::map<int, int>();
(*map2)[1] = 3;
std::cout << "Map1 at location 1 is: " << map1[1] << std::endl; //Prints 2
std::cout << "Map2 at location 1 is: " << (*map2)[1] << std::endl; // Prints 3
delete map2;
}
I try to print only a struct member from vector of my struct (struct pnt). let me be clear by showing this:
struct pnt {
char _name;
int _type;
bool _aux;
};
boost::copy(pntVec.begin(),pntVec.end()|
boost::adaptors::transformed(bind(&pnt::_type, _1)),
std::ostream_iterator<int>(std::cout, "\n"));
but I get an error. I will appreciate if you could please help me to find the reason for that.
Error:
error: no type named ‘type’ in ‘boost::mpl::eval_if_c<true, boost::range_const_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, void>, boost::range_mutable_iterator<const __gnu_cxx::__normal_iterator<int*, std::vector<int> >, void> >::f_ {aka struct boost::range_const_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> >, void>}’
NOTE: I can olny use C++98, boost v.1.56
Boost Adaptor adapts ranges, not single iterators. Similarily, the boost::copy algorithm expects two arguments, where the first one is a range, and the second an output iterator. Having said that, the correct syntax for extracting a single data member from a range, and copying it to an output iterator is:
boost::copy(pntVec | boost::adaptors::transformed(bind(&pnt::_type, _1))
, std::ostream_iterator<int>(std::cout, "\n"));
Alternatively, since Phoenix in a way supersedes Boost Bind + Boost Lambda, you could use Boost Phoenix:
boost::for_each(pntVec, std::cout << bind(&pnt::_type, arg1) << "\n");
or even without bind, if you don't fear a bit of arcane syntax:
boost::for_each(v, std::cout << (arg1->*&pnt::_type) << "\n");
That's pretty expressive. See it Live On Coliru
Also, note that there's mem_fn in Boost/c++11: pntVec | transformed(mem_fn(&pnt::_type))
I have a map that links a size_t to a pair, of size_t and int
std::map< size_type, std::pair<size_t, unsigned int> > mapVals;
essentially my understanding of this, is that maps work similar to stacks, and jst insert one after another, giving something similar to:
1 -> (2,2)
2 -> (4,7)
3 -> (8,5)
etc.
my question is, how do I obtain the value of the int. i.e. 2,7,5. I want to use this value as the max size of a while loop.
Maps are not similar to stacks; a stack maintains a first-in-last-out (FILO) strategy. A map is something that maps a key to a value.
If you do something like:
typedef std::pair<size_t,unsigned_int> my_pair;
// Insert elements
my_map[3] = my_pair(2,2);
my_map[9] = my_pair(4,7);
my_map[7] = my_pair(8,5);
You can retrieve the second element of your pair as:
my_map[9].second // evaluates to 7
To access the int you can do one of two things
unsigned int myint = mymap[key].second;
where key is of type size_t. This works because using [size_t] on the map returns a std::pair<size_t, unsigned int> then calling .second on this gets you the uint.
You could also use iterators
std::map<size_t, std::pair<size_t, unsigned int> >::iterator itr = mymap.begin(); // say
unsigned int myint = itr->second.second;
typedef std::map< size_type, std::pair<size_t, unsigned int> > mymapT;
mymapT mapVals;
... // fill the map
first = mapVals[1].second;
second = mapVals[2].second;
third = mapVals[3].second;
... // do something useful
You can do something like this:
typedef std::map< size_type, std::pair<size_t, unsigned int> > myMap;
myMap mapVals;
// ... populate
myVals[1] = std::pair<size_t, unsigned int>(2,2);
// ...
for (myMap::const_iterator it = myVals.begin(); it != myVals.end(); ++it)
unsigned int each_value = it->second.second;
The first it->second will give you the std::pair <size_t, unsigned int> element. The second second will give you the unsigned int contained in that pair.
I'm not sure what you want exactly
for (std::map< size_type, std::pair<size_t, unsigned int> >::iterator it = mapVals.begin(); it != mapVals.end() ; it++)
cout << it->second.first << " " << it->second.second << endl;
it->second : is the Value part of the map (in this case std::pair<size_t, unsigned int>)
it->second.second : is the second part of the pair (unsigned int)
I'm trying to print the second member variable of all items in an stl map using a lambda expression
map<int, int> theMap;
for_each(theMap.begin(), theMap.end(),
cout << bind(&pair<int, int>::second, _1) << constant(" "));
but this is not compiling. I essentially want to de-reference the placeholder. Any idea what I'm missing here?
Thanks in advance!
Try:
for_each(theMap.begin(), theMap.end(),
cout << bind(&map<int, int>::value_type::second, _1) << constant(" "));
std::map will add const to its key; this is to prevent messing up the ordering. Your pair should be:
std::pair<const int, int>
Like dirkgently suggests, use the value_type to always get the correct type. The verbosity is alleviated with a typedef:
typedef std::map<int, int> int_map;
int_map::value_type::second
When I work with BOOST_FOREACH, there isn't a problem with simple templates as vector. But when I try to iterate through map > for example I need to typedef the element type.
Is there any workaround?
There is a problem because it is a macro, and therefore cannot handle types containing commas (preprocessor doesn't know about templates).
You can also declare the variable before the loop, see documentation.
std::map<int, double> my_map;
//1)
typedef std::pair<int, double> MyPair;
BOOST_FOREACH(MyPair p, my_map) { ... }
//2)
std::pair<int, double> p;
BOOST_FOREACH(p, my_map) { ... }
Edit:
There is a further complication with std::map in particular: the value_type is not std::pair<Key, Value>, but std::pair<const Key, Value>.
Hence, if you go with the typedef, a more proper way (and the only way if you want to use a reference in the foreach loop) is to use
typedef std::pair<const int, double> MyPair;
//or
typedef std::map<int, double>::value_type MyPair;
BOOST_FOREACH(MyPair& ref, my_map) { ... }
However, that won't work if you want to use a variable declared before the loop, since you can't assign to a std::pair<const int, double> instance later (can't assign to the const field), in which case you can only use pair<int, double> as boost's manual shows.
If you need to iterate over a map, the easiest way is to use tuples, since getting the correct type in order to typedef, is troublesome. Here is how you can use tuples:
std::map<int, double> my_map;
int key;
double value;
BOOST_FOREACH(boost::tie(key, value), my_map) { ... }
Just a note, the commas will work here because parenthesis are placed around key and value. The preprocessor only understands commas and parenthesis(and c99 requires it to understand quotation marks also). So, it can't parse the <> in std::pair<int, double>. However, we can use parenthesis to help the preprocessor. For example, if we have a a function that returns a container that is called like this:
BOOST_FOREACH(int i, foo<int, int>()) { ... } //This won't compile
So, we can place parenthesis around an expression and it will help the preprocessor:
BOOST_FOREACH(int i, (foo<int, int>())) { ... } //This will compile
However, in the case of a map, we can't place parenthesis around the declaration(because its not an expression). So this won't work:
BOOST_FOREACH((std::pair<int, double> p), my_map) { ... } //This won't work
Because it will get transformed into something like this (std::pair<int, double> p) = *it, and that, of course, is incorrect C++. But using a tie will work:
BOOST_FOREACH(tie(key, value), my_map) { ... } //This will work
We just need to declare key and value outside of the loop(as shown above). Plus, it can make the loop have more meaningful names. You can write key instead of p.first, and value instead of p.second.
BOOST_FOREACH_PAIR is another option that works well in our experience:
http://lists.boost.org/Archives/boost/2009/09/156345.php
http://lists.boost.org/Archives/boost/2009/09/156366.php
This can be as simple as this:
BOOST_FOREACH(auto& p, my_map) { ... }
Using the C++11 standard, auto is like var in C#, it will do
BOOST_FOREACH(std::pair<int, double>& p, my_map) { ... }