print member of struct of a vector - c++

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))

Related

boost mpl count for simple example

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;

find a pair in set c++

if I have a set which contains pairs of int,
set<pair<int,int> > cells;
how can I find whether a pair exits in the set using 'find'. I can use 'find' for set with one value but cant do it for a pair.
I am trying like,
cells.insert(make_pair(1,1));
set<int,int>::iterator it;
it=cells.find(pair<int,int>(1,1));
error: no match for 'operator=' in 'it = cells.std::set<_Key, _Compare, _Alloc>::find<std::pair<int, int>, std::less<std::pair<int, int> >, std::allocator<std::pair<int, int> > >((*(const key_type*)(& std::pair<int, int>((* &1), (* &1)))))'|
Has anyone got any ideas? Thanks!
The problem is that your set is a set of a pair of integersstd::pair<int,int>, instead of just <int,int>. Changing that fixes your code. If you are using c++11 or later you can just use the auto keyword.
// Example program
#include <iostream>
#include <string>
#include <utility>
#include <set>
int main()
{
std::pair<int,int> p1(1,0);
std::pair<int,int> p2(2,1);
std::set<std::pair<int,int>> s;
s.insert(p1);
s.insert(p2);
auto it = s.find(p1);
std::cout << it->first << "," << it->second <<std::endl;
}
There seems to be a typo/misunderstanding about the type to be used for it. You need to use:
std::set<std::pair<int,int>>::iterator it;
It should be:
std::set<std::pair<int,int>> cells;
cells.insert(std::make_pair(1,1));
std::set<std::pair<int,int>>::iterator it; // here was the problem
it=cells.find(std::pair<int,int>(1,1));
In order to avoid these kind of mistakes you may use auto:
std::set<std::pair<int,int>> cells;
cells.insert(std::make_pair(1,1));
auto it =cells.find(std::pair<int,int>(1,1));
If you have to separate the definition and the use of it:
decltype(cells)::iterator it;
it=cells.find(std::pair<int,int>(1,1));
Live Demo

How to use a type array in map in c++

I want to have something like dictionary and because of this matter I used map. I want the "key" be an int and "value" to be an array. To reach this, I did the following but I can not go further,
typedef std::string RelArr[2];
std::map<int,RelArr> mymap;
Problem I can not assign anything to "value"
mymap.insert(myintnumber,"ValueOfFirstIndex","ValueOfSecondIndex");
I receive this error:
Multiple markers at this line
- deduced conflicting types for parameter ‘_InputIterator’ (‘int’ and ‘const char*’)
- candidates are:
- no matching function for call to ‘std::map<int, std::basic_string<char> [2]>::insert(int, const char [3], const char
[19])’
There are two problems here, the first is that arrays can not be assigned to, only copied to, which makes them unusable to put in containers. Use std::array instead:
typedef std::array<std::string, 2> RelArr;
The second problem is regarding what the error actually tells you is that you're using the std::map::insert function wrong, because there's no overload which takes two string literals.
If you want to insert an element in a std::map just do e.g.
mymap[myintnumber] = {{ "string1", "string2" }};
Or if you desperately want to use insert:
auto ret = mymap.insert(std::make_pair<int, RelArr>(
myothernumber, {{"hello", "world"}}));
if (ret.second == true)
std::cout << "Insertion was okay\n";
else
std::cout << "Insertion failed\n";

How can I use Boost.Bind on compound types?

I have std::map<int, std::pair<short, float> >, and I need to find the minimal short in this map. How can I use boost::bind with std::min_element() for this?
boost::lambda?
The map iterator will give you a pair where first is the int key and second is the map's pair value, so if you had an iterator it, you'd want the minimum of all the it->second.first values. The min_element function expects a comparison function for its third argument, so you need to build a comparison function that projects second.first of its two arguments.
We'll start with some typedefs to make the code more readable:
typedef std::pair<short, float> val_type;
typedef std::map<int, val_type> map_type;
map_type m;
We're going to use Boost.Lambda for its overloaded operators, allowing us to use operator<. Boost.Bind can bind member variables as well as member functions, so we'll take advantage of that, too.
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
using boost::bind;
// Comparison is (_1.second.first < _2.second.first)
std::cout <<
std::min_element(m.begin(), m.end(),
bind(&val_type::first, bind(&map_type::iterator::value_type::second, _1))
<
bind(&val_type::first, bind(&map_type::iterator::value_type::second, _2))
)->second.first;
That will also work with boost::lambda::bind.
min_element(map.begin(), map.end(),
compose2(less<short>(),
compose1(select1st<pair<short, float> >(),
select2nd<map<int, pair<short, float>
>::value_type>()),
compose1(select1st<pair<short, float> >(),
select2nd<map<int, pair<short, float>
>::value_type>()))
).second.first;
(Of course, somebody's going to complain that this is an abuse of STL and that these are extensions not in the C++ standard…)
bind cannot do this by itself, because first and second are exposed as fields, not methods (so you can't get away with something like mem_fun).
You could do this using your own functor of course though:
template <typename F, typename S>
struct select_first : std::binary_function<std::pair<F, S>&, F&>
{
F& operator()(std::pair<F, S>& toConvert)
{
return toConvert.first;
}
};

Accessing member variables through boost lambda placeholder

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