I have been going through the boost::range library and noticed boost::range_iterator and boost::iterator_range. I am confused with these terms here. Could anyone please explain what is the difference between two and when to use what? Also, it would be nice if you can point me to sample examples where the boost range library is used to know more about it apart from the documentation.
Could anyone please explain what is the difference between two and when to use what?
range_iterator is used for get type of range iterator in following way:
range_iterator< SomeRange >::type
It simillar in something to std::iterator_traits. For instance, you may get value type from iterator:
std::iterator_traits<int*>::value_type
iterator_range is bridge between ranges and iterators. For instance - you have pair of iterators, and you want pass them to algorithm which only accepts ranges. In that case you can wrap your iterators into range, using iterator_range. Or better - make_iterator_range - it will help to deduce types (like std::make_pair does):
make_iterator_range(iterator1,iterator2)
returns range.
Consider following example:
live demo
#include <boost/range/iterator_range.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/iterator.hpp>
#include <typeinfo>
#include <iostream>
#include <ostream>
using namespace boost;
using namespace std;
struct print
{
template<typename T>
void operator()(const T &t) const
{
cout << t << " ";
}
};
int main()
{
typedef int Array[20];
cout << typeid( range_iterator<Array>::type ).name() << endl;
Array arr={11,22,33,44,55,66,77,88};
boost::for_each( make_iterator_range(arr,arr+5) ,print());
}
Also, it would be nice if you can point me to sample examples where the boost range library is used to know more about it apart from the documentation
For quick summary - check this slides
Generally, you will not use boost::range_iterator directly, as it is a template metafunction which takes the range given (regardless of the type of the range), and returns the type of it's begin()/end() methods.
boost::iterator_range is used to create a new range from a pair of pre-existing iterators. This you will be more likely to use, usually when taking code that is still iterator based and using that to convert to a range.
Related
It seems that the compiler should be able to catch the fact that std::variant doesn't have iterator methods, but it seems that my code compiles with no problem (even if I randomly make up methods or member variables for the variant), but it crashes at runtime (rightfully so). Can someone shed some light on why this code compiles?
Note: this isn't blocking progress because now I'm using std::visit, but it would be nice to know why this is compiling.
I have tried using different variant patterns and they all compile. See code examples. You can pop this in to cppreferences, or godbolt and it should compile with C++17 flags or greater
#include <variant>
#include <string>
#include <cassert>
#include <iostream>
#include <list>
#include <map>
template<typename K, typename V>
//using var_maps = std::variant<std::map<K,V>, std::multimap<K,V> >;
//using var_maps = std::variant<std::list<int>, std::list<float> >;
using var_maps = std::variant<int, float>;
template <typename K, typename V>
void flat( const var_maps<K,V>& vmap)
{
//for(auto bIter = vmap.bexxxgin(), eIter = vmap.end(); bIter != eIter;
for(auto bIter = vmap.begin(), eIter = vmap.end(); bIter != eIter;
bIter = vmap.upper_bound( bIter->first ) )
{
}
}
My initial case was with maps, but it effectively compiles with anything. Additionally I can randomly replace begin() to any other word and it still compiles. I know the right way to do this is with visits. I am inevitably trying to have one function that handles both map and multimap and transform it to another data structure.
Thank you!
Your code compiles, because begin() and end() are dependent names - they depend on the function template arguments, so their lookup is postponed until the flat template instantiation. But it is never instantiated!
If you add the following, your code won't compile anymore:
int main () {
&flat<int, int>;
}
It "compiles" because the function is a template. No code is generated here and beyond basic syntax checking no complete checking can be done when the template is parsed.
This is because the compiler does not know whether the var_maps<K,V> contains begin() or not. There could be specializations.
You will receive the error when you instantiate var_maps, i.e. use var_maps with concrete types K and V.
I tried converting a substring (expressed by a pair of iterators) to an integer by boost::lexical_cast:
#include <iostream>
#include <boost/lexical_cast.hpp>
int main()
{
// assume [first, last) as substring
const std::string s("80");
auto first = s.begin(), last = s.end();
std::cout << boost::lexical_cast<int>(boost::make_iterator_range(first, last)) << std::endl;
return 0;
}
Output: (wandbox)
1
I got expected result (80) by workaround: boost::make_iterator_range(&*first, last - first).
Question: Why above code does not work as expected? And, where does 1 come from?
lexical_cast does not support iterator_range<std::string::(const_)iterator>
misuse of lexical_cast or iterator_range
bugs of lexical_cast or iterator_range
some other reason
The short answer is number 2 from your list, misuse of iterator_range - specifically you're using it without explicitly including the proper header for it.
Adding this:
#include <boost/range/iterator_range.hpp>
will make it behave as you expect.
The iterator_range and related functionality is split into two headers, iterator_range_core.hpp and iterator_range_io.hpp. The first one contains the class definition, the second one contains, among other things, the operator<< overload which makes it streamable and so usable by lexical_cast (usable in the sense that it will actually work as you expect).
Because you didn't included the proper header, you should normally get a compiler error, but in this case you're not getting it because lexical_cast.hpp includes the first of those two headers, iterator_range_core.hpp. This makes everything build fine, but it doesn't get the operator<< from the second header. Without that overload, when lexical_cast writes the range to the stream to perform the conversion, the best overload it finds is the one taking a bool parameter (because iterator_range has a default conversion to bool). That's why you're seeing that 1, because it's actually writing true to the underlying conversion stream.
You can test this easily with something like this:
auto someRange = boost::make_iterator_range(first, last);
std::cout << std::boolalpha<< someRange;
Without #include <boost/range/iterator_range.hpp> this will print true, with that include it will print your string (80).
I have the following simple Graph class, where for each Node, I store a set of outgoing Arcs:
#include <iostream>
#include <vector>
#include <map>
#include <set>
struct Arc {
char label;
int targetNode;
};
struct Graph {
std::vector<int> nodes;
std::map< int, std::set<Arc*> > outgoingArcsPerNode;
};
How can I provide a standard C++ iterator over all the arcs in the graph (order of iteration doesn't matter) that hides how the arcs are stored in the graph?
I would like to use it similar to the following:
int main() {
Graph g;
for (Graph::const_iterator it = g.arcsBegin(); it != g.arcsEnd(); ++it) {
Arc* a = *it;
}
}
I heard of boost::iterator, but I find it confusing. Maybe someone could give a hint how to use it in this case?
If you don't want to use boost, have a look at what iterators must provide : STL documentation.
Otherwise, you may use boost iterator library. See the iterator_facade tutorial which is very close to what you're asking.
Create class which has two iterators inside: one over map and another over set.
Each ++ is applied to set iterator. When it reaches the end, increment map iterator and reinitialize set iterator.
Also you can use boost::iterator_facade - it will not help to implement algorithm of the iteration, but will minimize your effort on making your iterator compatible to STL expectations...
Is it possible to get at the offset of a mpl::vector after performing a mpl::find<seq,type> on it ?
Put differently I want to do the compile time equavalent of:
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
typedef std::vector<int> v_type;
v_type v_int(3);
v_int[0] = 1;
v_int[1] = 2;
v_int[2] = 3;
v_type::iterator it= std::find( v_int.begin() ,v_int.end(),3);
std::cout << it - v_int.begin() << std::endl;
}
Failing this, my types in mpl::vector have a type_trait<T>::ordinal const hard-coded, I would like to avoid this if possible.
Important Note, I am also creating a boost::variant from the vector, and I see I can get at the ordinal by performing a runtime function variant::which(). However, this requires I create a dummy object with default-initialized values. This is quite uggly. If you know some other way of doing it with variant, that would be a solution to my problem as well.
If what you're looking for is a kind of indexOf feature, I guess the example from Boost.MPL doc concerning find will do the trick:
typedef vector<char,int,unsigned,long,unsigned long> types;
typedef find<types,unsigned>::type iter;
BOOST_MPL_ASSERT(( is_same< deref<iter>::type, unsigned > ));
BOOST_MPL_ASSERT_RELATION( iter::pos::value, ==, 2 );
Their is a metafunction in the itterator category to do just this, it is called distance.
p.s., apologies for answering my own question so quickly. I just stumbled on the solution.
I don't know how to use the hash function in C++, but I know that we can use hash_map. Does g++ support that by simply including #include <hash_map>? What is a simple example using hash_map?
The current C++ standard does not have hash maps, but the coming C++0x standard does, and these are already supported by g++ in the shape of "unordered maps":
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std;
int main() {
unordered_map <string, int> m;
m["foo"] = 42;
cout << m["foo"] << endl;
}
In order to get this compile, you need to tell g++ that you are using C++0x:
g++ -std=c++0x main.cpp
These maps work pretty much as std::map does, except that instead of providing a custom operator<() for your own types, you need to provide a custom hash function - suitable functions are provided for types like integers and strings.
#include <tr1/unordered_map> will get you next-standard C++ unique hash container. Usage:
std::tr1::unordered_map<std::string,int> my_map;
my_map["answer"] = 42;
printf( "The answer to life and everything is: %d\n", my_map["answer"] );
Wikipedia never lets down:
http://en.wikipedia.org/wiki/Hash_map_(C%2B%2B)
hash_map is a non-standard extension. unordered_map is part of std::tr1, and will be moved into the std namespace for C++0x. http://en.wikipedia.org/wiki/Unordered_map_%28C%2B%2B%29
The name accepted into TR1 (and the draft for the next standard) is std::unordered_map, so if you have that available, it's probably the one you want to use.
Other than that, using it is a lot like using std::map, with the proviso that when/if you traverse the items in an std::map, they come out in the order specified by operator<, but for an unordered_map, the order is generally meaningless.