Easy way to iterate std::map<...>? - c++

I have a variable with a type similar to:
map<bool, map<string, pair<string, int> > > items;
which I pass around to different functions.
Is there a less tedious way for me to iterate over it then saying
for (map<bool, map<string, pair<string, int> > >::iterator p = items.begin();
p != items.end(); p++)
...
every time? (i.e. can I somehow omit the type name, with a macro or template or something? A manual typedef doesn't count.)
I'm using Visual C++ 2008.

You can use BOOST_FOREACH. You'll have to use a typedef for clarity though:
typedef std::map<std::string, std::pair<std::string, int> > inner_map;
typedef std::pair<bool, inner_map> map_entry;
BOOST_FOREACH(map_entry& p, items)
{
...
}
I prefer a plain typedef and a for loop though. I see typedef the same way I see a variable assignment:
typedef std::map<std::string, std::pair<std::string, int> > inner_map;
typedef std::map<bool, inner_map>::iterator map_iterator;
for (map_iterator i = items.begin(); i != items.end(); ++i)
{
...
}
Those typedefs can also be private members. This coding style is much clearer, since you see at a glance the types involved.
Or you can use plain std::for_each, if you are ready to write a functor. I don't really like this in standard C++ since the loop body is no longer local (this can be an advantage in some cases however):
struct some_functor
{
template <typename K, typename V>
void operator()(std::pair<K, V>& item)
{
// In the context below, K is bool and
// V is map<string, pair<string, int> >
}
};
and then later
std::for_each(items.begin(), items.end(), some_functor());
If you upgrade to VS2010, you have alternatives: auto and std::for_each with a lambda (which I prefer). With C++0x, technically, you also have range-based for loops (not available in VS2010).
To conclude, I'd do:
class meaningful_data
{
typedef std::map<std::string, std::pair<std::string, int> > inner_map;
std::map<bool, inner_map> items;
public:
typedef std::pair<bool, inner_map> value_type;
typedef std::map<bool, inner_map>::iterator iterator;
typedef std::map<bool, inner_map>::const_iterator const_iterator;
iterator begin() { return items.begin(); }
const_iterator begin() const { return items.begin(); }
iterator end() { return items.end(); }
const_iterator end() const { return items.end(); }
// Add some interface here (as small as possible)
};
and iterate like this:
for (meaningful_data::iterator i = d.begin(); i != d.end(); ++i)
{
...
}
or
BOOST_FOREACH(meaningful_data::value_type& i, d)
{
...
}
You'll probably want to encapsulate such a complex type, at least with a few typedefs (you're not forced to use a full blown class if the inner_map type ought to be public).

I recommend using typedef, which is probably a way of saying "no, you can't" ;)
Otherwise, if you were to switch to a compiler that supports auto as defined in C++0x, you could say:
for (auto p = items.begin(); p != items.end(); ++p) // ...
(Oh, by the way, I also recommend ++p to avoid copying the iterator)

You could use the standard for_each algorithm:
#include <algorithm>
struct your_functor {
template<typename T>
void operator()(T const &item) {
// Your loop body here.
}
}
std::for_each(items.begin(), items.end(), your_functor());

You can use BOOST_AUTO

You can write your own algorithm function.
template<class C>
void do_what_I_want_to_do(C& c)
{
for (C::iterator i = c.begin(); i != c.end(); ++c)
{
// do something
}
}
do_what_I_want_to_do(items);
That may or may not be an improvement for you.

Sure, use typedefs:
typedef std::map<std::string, std::pair<std::string, int> > Item;
typedef Item::const_iterator ItemCItr;
typedef std::map<bool, Item> ItemMap;
typedef ItemMap::const_iterator ItemMapItr;
for (ItemMapItr it = m.begin(), end = m.end(); it != end; ++it)
{
const Item & item = it->second;
for (ItemItr jt = item.begin(), jend = item.end(); jt != jend; ++jt)
{
/* ... */
}
}

After seeing all the "no you can't do this" answers, I took some time to try to find at least a partial workaround.
This version almost works, with the caveat that every reference to the iterator also requires a reference to the container. It might not be a good idea to actually use this (because of the heap allocation and other things) but I thought I'd share it anyway:
#include <map>
#include <iostream>
using namespace std;
template<typename T>
bool _end(T& src, void *iterator = NULL)
{ return static_cast<typename T::iterator>(iterator) < src.end(); }
template<typename T>
struct _IterateHelper
{
typename T::iterator *pIterator;
_IterateHelper(T& dummy, void *&p)
{ this->pIterator = static_cast<typename T::iterator *>(p); }
~_IterateHelper() { delete pIterator; }
};
template<typename T>
_IterateHelper<T> _iterateHelper(T& dummy, void *&p)
{ return _IterateHelper<T>(dummy, p); }
template<typename T>
bool _iterate(T& container, void *&iterator)
{
typename T::iterator *&p =
reinterpret_cast<typename T::iterator *&>(iterator);
if (iterator == NULL) { p = new typename T::iterator(container.begin()); }
else { ++*p; }
return *p != container.end();
}
template<typename T>
typename T::iterator & I(T& container, void *&pIterator)
{ return *static_cast<typename T::iterator *>(pIterator); }
#define FOR_EACH(state, container) \
void *state = NULL; \
for (_iterateHelper(container, state); _iterate(container, state); )
int main()
{
map<string, string> m;
items["a"] = "b";
items["1"] = "2";
FOR_EACH(p, items)
cout << I(items, p)->first << ": " << I(items, p)->second << endl;
}

Qt offers its own foreach implementation, so i just reworked it for std::map - basically just a simple modification (->second). Tested on MSVC and gcc.
struct ForeachBaseBase {};
template <typename T1, typename T2>
class ForeachBase: public ForeachBaseBase
{
public:
inline ForeachBase(const std::map<T1,T2>& t): c(t), brk(0), i(c.begin()), e(c.end()){}
const std::map<T1,T2> c;
mutable int brk;
mutable typename std::map<T1,T2>::const_iterator i, e;
inline bool condition() const { return (!brk++ && i != e);}
};
template <typename T1, typename T2> inline std::map<T1,T2> *pMForeachPointer(const std::map<T1,T2> &) { return 0; }
template <typename T1, typename T2> inline ForeachBase<T1,T2> pMForeachBaseNew(const std::map<T1,T2>& t)
{ return ForeachBase<T1,T2>(t); }
template <typename T1, typename T2>
inline const ForeachBase<T1,T2> *pMForeachBase(const ForeachBaseBase *base, const std::map<T1,T2> *)
{ return static_cast<const ForeachBase<T1,T2> *>(base); }
#if defined(Q_CC_MIPS)
/*
Proper for-scoping in MIPSpro CC
*/
# define MAP_FOREACH(variable,container) \
if(0){}else \
for (const ForeachBaseBase &_container_ = pMForeachBaseNew(container); \
pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->condition(); \
++pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->i) \
for (variable = pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->i->second; \
pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->brk; \
--pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->brk)
#elif defined(Q_CC_DIAB)
// VxWorks DIAB generates unresolvable symbols, if container is a function call
# define MAP_FOREACH(variable,container) \
if(0){}else \
for (const ForeachBaseBase &_container_ = pMForeachBaseNew(container); \
pMForeachBase(&_container_, (__typeof__(container) *) 0)->condition(); \
++pMForeachBase(&_container_, (__typeof__(container) *) 0)->i) \
for (variable = pMForeachBase(&_container_, (__typeof__(container) *) 0)->i->second; \
pMForeachBase(&_container_, (__typeof__(container) *) 0)->brk; \
--pMForeachBase(&_container_, (__typeof__(container) *) 0)->brk)
#else
# define MAP_FOREACH(variable, container) \
for (const ForeachBaseBase &_container_ = pMForeachBaseNew(container); \
pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->condition(); \
++pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->i) \
for (variable = pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->i->second; \
pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->brk; \
--pMForeachBase(&_container_, true ? 0 : pMForeachPointer(container))->brk)
#endif // MSVC6 || MIPSpro
#define mforeach MAP_FOREACH

Related

Template function with template argument parametrized over int

Without using the features of C++11 and higher (I will accept them but would prefer C++98),
I have to write a template function with argument T which is an STL container of ints. It receives such a container along with another int which it tries to search for,
Right now I have this but it doesn't compile:
template <template<int> class T>
T::iterator easyfind(T &container, int val)
{
T::iterator it = container.begin();
for ( ; it != container.end(); it++)
if (val == *it)
break ;
return (it);
}
I wonder if I can somehow force the T parameter to always be a class template that is parametrized over integers... I tried writing T<int> but it still doesn't compile.
[NOTE] This answer uses C++20. #PatrickRoberts made me notice that you were preferably requesting a C++98 solution. I leave it anyway because it may be of any help to you.
You can just add a requirement for your template, checking the container's type is int.
[Demo]
#include <iostream> // cout
#include <list>
#include <type_traits> // is_same
#include <vector>
template <typename C>
requires std::is_same<typename C::value_type, int>::value
auto easyfind(const C& container, int val)
{
for (auto it{std::cbegin(container)}; it != std::cend(container); ++it)
{
if (val == *it) { return it; }
}
return std::cend(container);
}
int main()
{
std::vector<int> vi{1, 2, 3};
if (auto it{easyfind(vi, 2)}; it != std::cend(vi))
{
std::cout << *it << "\n";
}
std::list<int> li{4, 5, 6};
if (auto it{easyfind(li, 8)}; it != std::cend(li))
{
std::cout << *it << "\n";
}
std::vector<double> vd{0.5, 1.3, 2.8};
//if (auto it{easyfind(vd, 1.3)}; it != std::cend(vd)) // error
//{
// std::cout << *it << "\n";
//}
}
Though there is an accepted answer, let me try to solve it using C++98.
DEMO
#include <vector>
#include <iostream>
namespace details{
struct true_type{static const bool value = true;};
struct false_type{static const bool value = false;};
template<typename T1,typename T2> struct is_same : false_type{};
template<typename T> struct is_same<T,T>:true_type{};
#define STATIC_ASSERT(expr, msg) \
{ \
char STATIC_ASSERT##msg[(expr)?1:-1]; \
}
};
template <class T>
typename T::iterator easyfind(T &container, int val)
{
using namespace details;
//static_assert can be used in C++11 onwards
STATIC_ASSERT((is_same<typename T::value_type,int>::value == true_type::value),InavalidType);
typename T::iterator it = container.begin();
for ( ; it != container.end(); it++)
if (val == *it)
break ;
return (it);
}
int main(){
std::vector<int> a{1,2,3};
auto it = easyfind(a,1);
if(it != a.end())
std::cout<<*it<<std::endl;
auto it2 = easyfind(a,4);
if(it2 != a.end())
std::cout<<*it<<std::endl;
else
std::cout<<"Not Found"<<std::endl;
std::vector<double> b{1.0,2.0,3.0};
// std::vector<int>::iterator it3 = easyfind(b,1.0); //error
return 0;
}
template <template<int> class T> is not what you expect.
You want
template <template <typename> class Container>
typename Container<int>::iterator easyfind(Container<int> &container, int val)
{
#if 1 // Your code
typename Container<int>::iterator it = container.begin();
for ( ; it != container.end(); it++)
if (val == *it)
break ;
return it;
#else // code with <algorithm>
return std::find(container.begin(), container.end(), val);
#endif
}
Unfortunately, std::vector doesn't match Container, as it has extra template parameter (Allocator, which is defaulted).
You might add overload:
template <template <typename, typename> class Container, typename Alloc>
typename Container<int, Alloc>::iterator easyfind(Container<int, Alloc> &container, int val)
C++11 would allow template <template <typename...> class Container.
Simpler would be to use container directly as type:
template <typename Container>
#if 1 // No SFINAE
typename Container::iterator
#else // SFINAE with traits from C++11, which can be written trivially in C++98
typename std::enable_if<std::is_same<int, typename Container::value_type>>::type
#endif
easyfind(Container& container, int val)
{
#if 1 // Your code
typename Container::iterator it = container.begin();
for ( ; it != container.end(); it++)
if (val == *it)
break ;
return it;
#else // code with <algorithm>
return std::find(container.begin(), container.end(), val);
#endif
}
but more generic would be to drop int requirement completely:
template <typename Container>
typename Container::iterator
easyfind(Container& container, typename Container::const_reference val)
{
return std::find(container.begin(), container.end(), val);
}

What is the type for dereferencing an iterator to a map or some other composite types in C++

My question is what is the type for *it, if it is of the type of std::map<std::string, int>::iterator
As a follow up to that question, if I would like to use accumulate to calculate all the map values, how could I do? Thanks.
It's a reference to an std::pair<const KeyT, ValueT> (where KeyT and ValueT are the key and value parameters of the map). You may write some kind of iterator wrapper to wrap map iterators, make them return just the value and then use std::accumulate:
template<typename ItT>
struct SecondIterator
{
ItT it;
SecondIterator(const ItT &it) : it(it) {}
SecondIterator &operator++()
{
++it;
return *this;
}
SecondIterator operator++(int)
{
SecondIterator t=*this;
++(*this);
return t;
}
SecondIterator &operator--()
{
--it;
return *this;
}
SecondIterator operator--(int)
{
SecondIterator t=*this;
--(*this);
return t;
}
typename ItT::value_type::second_type &operator*()
{
return it->second;
}
bool operator==(const SecondIterator &other)
{
return it==other.it;
}
bool operator!=(const SecondIterator &other)
{
return it!=other.it;
}
};
(probably I forgot some typename here and there, but you got the idea)
but if you ask me it's definitely not worth the effort.
If you want to accumulate the mapped_type of a std::map, perhaps the following helper classes will be of interest:
#include <functional>
#include <numeric>
#include <utility>
#ifndef USE_CXX11
#if (__cplusplus >= 201100) || (_MSC_VER >= 1800)
#define USE_CXX11 1
#endif
#endif
#if USE_CXX11
/*
map_value_accumulator - helper class that allows iterators of std::map
to be used with std::accumulate
*/
template <typename T, typename Op = std::plus<typename T::mapped_type> >
class map_value_accumulator
{
public:
typedef typename T::value_type pair_type;
typedef typename T::mapped_type value_type;
value_type operator()( value_type acc, pair_type const& p) const {
return op_( acc, p.second);
}
map_value_accumulator() : op_(Op()) {};
map_value_accumulator(Op&& op) : op_(op) {};
private:
Op op_;
};
/*
make_map_value_accumulator() - function that uses argument deduction to
help create map_value_accumulator objects
*/
// make_map_value_accumulator() that returns a user-specified operation
// the operation defaults to std::plus<> is not specified
template <typename T, typename Op = std::plus<typename T::mapped_type> >
map_value_accumulator< T, Op>
make_map_value_accumulator( T const& m, Op&& op = Op())
{
return map_value_accumulator< T, Op>(std::forward<Op>(op));
}
#else
/*
map_value_accumulator - helper class that allows iterators of std::map
to be used with std::accumulate
*/
template <typename T, typename Op = std::plus<typename T::mapped_type> >
class map_value_accumulator
{
public:
typedef typename T::value_type pair_type;
typedef typename T::mapped_type value_type;
typedef std::plus<typename T::mapped_type> default_operator_type;
value_type operator()( value_type acc, pair_type const& p) const {
return op_( acc, p.second);
}
map_value_accumulator() : op_(default_operator_type()) {};
map_value_accumulator(Op op) : op_(op) {};
private:
Op op_;
};
/*
make_map_value_accumulator() - function that uses argument deduction to
help create map_value_accumulator objects
*/
template <typename T, typename Op>
map_value_accumulator< T, Op>
make_map_value_accumulator( T const& m, Op const& op)
{
return map_value_accumulator< T, Op>(op);
}
template <typename T>
map_value_accumulator< T, std::plus<typename T::mapped_type> >
make_map_value_accumulator( T const& m)
{
typedef std::plus<typename T::mapped_type> default_operator_type;
return map_value_accumulator< T, default_operator_type>();
}
#endif /* USE_CXX11 */
#include <iostream>
#include <ostream>
#include <map>
int main()
{
std::map<char, int> m;
m.insert(std::make_pair('a', 1));
m.insert(std::make_pair('z', 26));
m.insert(std::make_pair('c', 3));
m.insert(std::make_pair('b', 2));
m.insert(std::make_pair('?', -2));
using std::cout;
using std::endl;
// directly create the map_value_accumulator functor (defaults to std::plus)
cout << accumulate(m.begin(), m.end(), 0, map_value_accumulator<std::map<char,int> >()) << endl;
// create a map_value_accumulator deduced from the user's map type (default to std::plus)
cout << accumulate(m.begin(), m.end(), 0, make_map_value_accumulator(m)) << endl;
// create a map_value_accumulator deduced from the user's map type and specifying an operation functor
cout << accumulate(m.begin(), m.end(), 1, make_map_value_accumulator(m, std::multiplies<int>())) << endl;
#if USE_CXX11
cout << "accumulate with a lambda: ";
// create a map_value_accumulator deduced from the user's map type and specifying a lambda for the operation
// (will perform a sum of squares)
cout << accumulate(m.begin(), m.end(), 0, make_map_value_accumulator(m, [](int x, int y){ return x + y * y; })) << endl;
#endif
return 0;
}
Note: I've updated the example. The first example would not work with lambdas and didn't work with MS compilers older than VS 2013. The new example has some conditional compilation that has a C++11 implementation (that supports lambdas) and a non-C++11 variant that works with VS 2003 and later and presumably any reasonable version of GCC.

Flattening iterator

Is there any existing iterator implementation (perhaps in boost) which implement some sort of flattening iterator?
For example:
unordered_set<vector<int> > s;
s.insert(vector<int>());
s.insert({1,2,3,4,5});
s.insert({6,7,8});
s.insert({9,10,11,12});
flattening_iterator<unordered_set<vector<int> >::iterator> it( ... ), end( ... );
for(; it != end; ++it)
{
cout << *it << endl;
}
//would print the numbers 1 through 12
I don't know of any implementation in a major library, but it looked like an interesting problem so I wrote a basic implementation. I've only tested it with the test case I present here, so I don't recommend using it without further testing.
The problem is a bit trickier than it looks because some of the "inner" containers may be empty and you have to skip over them. This means that advancing the flattening_iterator by one position may actually advance the iterator into the "outer" container by more than one position. Because of this, the flattening_iterator needs to know where the end of the outer range is so that it knows when it needs to stop.
This implementation is a forward iterator. A bidirectional iterator would also need to keep track of the beginning of the outer range. The flatten function templates are used to make constructing flattening_iterators a bit easier.
#include <iterator>
// A forward iterator that "flattens" a container of containers. For example,
// a vector<vector<int>> containing { { 1, 2, 3 }, { 4, 5, 6 } } is iterated as
// a single range, { 1, 2, 3, 4, 5, 6 }.
template <typename OuterIterator>
class flattening_iterator
{
public:
typedef OuterIterator outer_iterator;
typedef typename OuterIterator::value_type::iterator inner_iterator;
typedef std::forward_iterator_tag iterator_category;
typedef typename inner_iterator::value_type value_type;
typedef typename inner_iterator::difference_type difference_type;
typedef typename inner_iterator::pointer pointer;
typedef typename inner_iterator::reference reference;
flattening_iterator() { }
flattening_iterator(outer_iterator it) : outer_it_(it), outer_end_(it) { }
flattening_iterator(outer_iterator it, outer_iterator end)
: outer_it_(it),
outer_end_(end)
{
if (outer_it_ == outer_end_) { return; }
inner_it_ = outer_it_->begin();
advance_past_empty_inner_containers();
}
reference operator*() const { return *inner_it_; }
pointer operator->() const { return &*inner_it_; }
flattening_iterator& operator++()
{
++inner_it_;
if (inner_it_ == outer_it_->end())
advance_past_empty_inner_containers();
return *this;
}
flattening_iterator operator++(int)
{
flattening_iterator it(*this);
++*this;
return it;
}
friend bool operator==(const flattening_iterator& a,
const flattening_iterator& b)
{
if (a.outer_it_ != b.outer_it_)
return false;
if (a.outer_it_ != a.outer_end_ &&
b.outer_it_ != b.outer_end_ &&
a.inner_it_ != b.inner_it_)
return false;
return true;
}
friend bool operator!=(const flattening_iterator& a,
const flattening_iterator& b)
{
return !(a == b);
}
private:
void advance_past_empty_inner_containers()
{
while (outer_it_ != outer_end_ && inner_it_ == outer_it_->end())
{
++outer_it_;
if (outer_it_ != outer_end_)
inner_it_ = outer_it_->begin();
}
}
outer_iterator outer_it_;
outer_iterator outer_end_;
inner_iterator inner_it_;
};
template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator it)
{
return flattening_iterator<Iterator>(it, it);
}
template <typename Iterator>
flattening_iterator<Iterator> flatten(Iterator first, Iterator last)
{
return flattening_iterator<Iterator>(first, last);
}
The following is a minimal test stub:
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
int main()
{
// Generate some test data: it looks like this:
// { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 } }
std::vector<std::vector<int>> v(3);
int i(0);
for (auto it(v.begin()); it != v.end(); ++it)
{
it->push_back(i++); it->push_back(i++);
it->push_back(i++); it->push_back(i++);
}
// Flatten the data and print all the elements:
for (auto it(flatten(v.begin(), v.end())); it != v.end(); ++it)
{
std::cout << *it << ", ";
}
std::cout << "\n";
// Or, since the standard library algorithms are awesome:
std::copy(flatten(v.begin(), v.end()), flatten(v.end()),
std::ostream_iterator<int>(std::cout, ", "));
}
Like I said at the beginning, I haven't tested this thoroughly. Let me know if you find any bugs and I'll be happy to correct them.
I decided to "improve" a bit on the flattening iterator concept, though as noted by James you are stuck using Ranges (except for the inner most container), so I just used ranges through and through and thus obtained a flattened range, with an arbitrary depth.
First I used a building brick:
template <typename C>
struct iterator { using type = typename C::iterator; };
template <typename C>
struct iterator<C const> { using type = typename C::const_iterator; };
And then defined a (very minimal) ForwardRange concept:
template <typename C>
class ForwardRange {
using Iter = typename iterator<C>::type;
public:
using pointer = typename std::iterator_traits<Iter>::pointer;
using reference = typename std::iterator_traits<Iter>::reference;
using value_type = typename std::iterator_traits<Iter>::value_type;
ForwardRange(): _begin(), _end() {}
explicit ForwardRange(C& c): _begin(begin(c)), _end(end(c)) {}
// Observers
explicit operator bool() const { return _begin != _end; }
reference operator*() const { assert(*this); return *_begin; }
pointer operator->() const { assert(*this); return &*_begin; }
// Modifiers
ForwardRange& operator++() { assert(*this); ++_begin; return *this; }
ForwardRange operator++(int) { ForwardRange tmp(*this); ++*this; return tmp; }
private:
Iter _begin;
Iter _end;
}; // class ForwardRange
This is our building brick here, though in fact we could make do with just the rest:
template <typename C, size_t N>
class FlattenedForwardRange {
using Iter = typename iterator<C>::type;
using Inner = FlattenedForwardRange<typename std::iterator_traits<Iter>::value_type, N-1>;
public:
using pointer = typename Inner::pointer;
using reference = typename Inner::reference;
using value_type = typename Inner::value_type;
FlattenedForwardRange(): _outer(), _inner() {}
explicit FlattenedForwardRange(C& outer): _outer(outer), _inner() {
if (not _outer) { return; }
_inner = Inner{*_outer};
this->advance();
}
// Observers
explicit operator bool() const { return static_cast<bool>(_outer); }
reference operator*() const { assert(*this); return *_inner; }
pointer operator->() const { assert(*this); return _inner.operator->(); }
// Modifiers
FlattenedForwardRange& operator++() { ++_inner; this->advance(); return *this; }
FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }
private:
void advance() {
if (_inner) { return; }
for (++_outer; _outer; ++_outer) {
_inner = Inner{*_outer};
if (_inner) { return; }
}
_inner = Inner{};
}
ForwardRange<C> _outer;
Inner _inner;
}; // class FlattenedForwardRange
template <typename C>
class FlattenedForwardRange<C, 0> {
using Iter = typename iterator<C>::type;
public:
using pointer = typename std::iterator_traits<Iter>::pointer;
using reference = typename std::iterator_traits<Iter>::reference;
using value_type = typename std::iterator_traits<Iter>::value_type;
FlattenedForwardRange(): _range() {}
explicit FlattenedForwardRange(C& c): _range(c) {}
// Observers
explicit operator bool() const { return static_cast<bool>(_range); }
reference operator*() const { return *_range; }
pointer operator->() const { return _range.operator->(); }
// Modifiers
FlattenedForwardRange& operator++() { ++_range; return *this; }
FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }
private:
ForwardRange<C> _range;
}; // class FlattenedForwardRange
And apparently, it works
I arrive a little late here, but I have just published a library (multidim) to deal with such problem. The usage is quite simple: to use your example,
#include "multidim.hpp"
// ... create "s" as in your example ...
auto view = multidim::makeFlatView(s);
// view offers now a flattened view on s
// You can now use iterators...
for (auto it = begin(view); it != end(view); ++it) cout << *it << endl;
// or a simple range-for loop
for (auto value : view) cout << value;
The library is header-only and has no dependencies. Requires C++11 though.
you can make one using iterator facade in boost.
I wrote iterator product which you can use as a template perhaps:
http://code.google.com/p/asadchev/source/browse/trunk/work/cxx/iterator/product.hpp
In addition to the answer of Matthieu, you can automatically count the amount of dimensions of the iterable/container. But first we must set up a rule when something is an iterable/container:
template<class T, class R = void>
struct AliasWrapper {
using Type = R;
};
template<class T, class Enable = void>
struct HasValueType : std::false_type {};
template<class T>
struct HasValueType<T, typename AliasWrapper<typename T::value_type>::Type> : std::true_type {};
template<class T, class Enable = void>
struct HasConstIterator : std::false_type {};
template<class T>
struct HasConstIterator<T, typename AliasWrapper<typename T::const_iterator>::Type> : std::true_type {};
template<class T, class Enable = void>
struct HasIterator : std::false_type {};
template<class T>
struct HasIterator<T, typename AliasWrapper<typename T::iterator>::Type> : std::true_type {};
template<class T>
struct IsIterable {
static constexpr bool value = HasValueType<T>::value && HasConstIterator<T>::value && HasIterator<T>::value;
};
We can count the dimensions as follows:
template<class T, bool IsCont>
struct CountDimsHelper;
template<class T>
struct CountDimsHelper<T, true> {
using Inner = typename std::decay_t<T>::value_type;
static constexpr int value = 1 + CountDimsHelper<Inner, IsIterable<Inner>::value>::value;
};
template<class T>
struct CountDimsHelper<T, false> {
static constexpr int value = 0;
};
template<class T>
struct CountDims {
using Decayed = std::decay_t<T>;
static constexpr int value = CountDimsHelper<Decayed, IsIterable<Decayed>::value>::value;
};
We then can create a view wrapper, that contains a begin() and end() function.
template<class Iterable, int Dims>
class Flatten {
public:
using iterator = FlattenIterator<Iterable, Dims>;
private:
iterator _begin{};
iterator _end{};
public:
Flatten() = default;
template<class I>
explicit Flatten(I&& iterable) :
_begin(iterable),
_end(iterable)
{}
iterator begin() const {
return _begin;
}
iterator end() const {
return _end;
}
};
To make the creation of the object Flatten a bit easier, we define a helper function:
template<class Iterable>
Flatten<std::decay_t<Iterable>, CountDims<Iterable>::value - 1> flatten(Iterable&& iterable) {
return Flatten<std::decay_t<Iterable>, CountDims<Iterable>::value - 1>(iterable);
}
Usage:
std::vector<std::vector<int>> vecs = {{1,2,3}, {}, {4,5,6}};
for (int i : flatten(vecs)) {
// do something with i
}

Which C++ Standard Library wrapper functions do you use?

This question, asked this morning, made me wonder which features you think are missing from the C++ Standard Library, and how you have gone about filling the gaps with wrapper functions. For example, my own utility library has this function for vector append:
template <class T>
std::vector<T> & operator += ( std::vector<T> & v1,
const std::vector <T> & v2 ) {
v1.insert( v1.end(), v2.begin(), v2.end() );
return v1;
}
and this one for clearing (more or less) any type - particularly useful for things like std::stack:
template <class C>
void Clear( C & c ) {
c = C();
}
I have a few more, but I'm interested in which ones you use? Please limit answers to wrapper functions - i.e. no more than a couple of lines of code.
Quite often I'd use vector as a set of items in no particular order (and, obviously, when I don't need fast is-this-element-in-the-set checks). In these cases, calling erase() is a waste of time since it will reorder the elements and I don't care about order. That's when the O(1) function below comes in handy - just move the last element at the position of the one you'd want to delete:
template<typename T>
void erase_unordered(std::vector<T>& v, size_t index)
{
v[index] = v.back();
v.pop_back();
}
boost::array
contains(container, val) (quite simple, but convenient).
template<typename C, typename T>
bool contains(const C& container, const T& val) {
return std::find(std::begin(container), std::end(container), val) != std::end(container);
}
remove_unstable(begin, end, value)
A faster version of std::remove with the exception that it doesn't preserve the order of the remaining objects.
template <typename T>
T remove_unstable(T start, T stop, const typename T::value_type& val){
while(start != stop) {
if (*start == val) {
--stop;
::std::iter_swap(start, stop);
} else {
++start;
}
}
return stop;
}
(in the case of a vector of pod types (int, float etc) and almost all objects are removed, std::remove might be faster).
template < class T >
class temp_value {
public :
temp_value(T& var) : _var(var), _original(var) {}
~temp_value() { _var = _original; }
private :
T& _var;
T _original;
temp_value(const temp_value&);
temp_value& operator=(const temp_value&);
};
Ok, since it seems this isn't as straight-forward as I thought, here's an explanation:
In its constructor temp_value stores a reference to a variable and a copy of the variable's original value. In its destructor it restores the referenced variable to its original value. So, no matter what you did to the variable between construction and destruction, it will be reset when the temp_value object goes out of scope.
Use it like this:
void f(some_type& var)
{
temp_value<some_type> restorer(var); // remembers var's value
// change var as you like
g(var);
// upon destruction restorer will restore var to its original value
}
Here's another approach that uses the scope-guard trick:
namespace detail
{
// use scope-guard trick
class restorer_base
{
public:
// call to flag the value shouldn't
// be restored at destruction
void dismiss(void) const
{
mDismissed = true;
}
protected:
// creation
restorer_base(void) :
mDismissed(false)
{}
restorer_base(const restorer_base& pOther) :
mDismissed(pOther.is_dismissed())
{
// take "ownership"
pOther.dismiss();
}
~restorer_base(void) {} // non-virtual
// query
bool is_dismissed(void) const
{
return mDismissed;
}
private:
// not copy-assignable, copy-constructibility is ok
restorer_base& operator=(const restorer_base&);
mutable bool mDismissed;
};
// generic single-value restorer, could be made
// variadic to store and restore several variables
template <typename T>
class restorer_holder : public restorer_base
{
public:
restorer_holder(T& pX) :
mX(pX),
mValue(pX)
{}
~restorer_holder(void)
{
if (!is_dismissed())
mX = mValue;
}
private:
// not copy-assignable, copy-constructibility is ok
restorer_holder& operator=(const restorer_holder&);
T& mX;
T mValue;
};
}
// store references to generated holders
typedef const detail::restorer_base& restorer;
// generator (could also be made variadic)
template <typename T>
detail::restorer_holder<T> store(T& pX)
{
return detail::restorer_holder<T>(pX);
}
It's just a bit more boiler-plate code, but allows a cleaner usage:
#include <iostream>
template <typename T>
void print(const T& pX)
{
std::cout << pX << std::endl;
}
void foo(void)
{
double d = 10.0;
double e = 12.0;
print(d); print(e);
{
restorer f = store(d);
restorer g = store(e);
d = -5.0;
e = 3.1337;
print(d); print(e);
g.dismiss();
}
print(d); print(e);
}
int main(void)
{
foo();
int i = 5;
print(i);
{
restorer r = store(i);
i *= 123;
print(i);
}
print(i);
}
It removes its ability to be used in a class, though.
Here's a third way to achieve the same effect (which doesn't suffer from the problems of potentially throwing destructors):
Implementation:
//none -- it is built into the language
Usage:
#include <iostream>
template <typename T>
void print(const T& pX)
{
std::cout << pX << std::endl;
}
void foo(void)
{
double d = 10.0;
double e = 12.0;
print(d); print(e);
{
double f(d);
double g(e);
f = -5.0;
g = 3.1337;
print(f); print(g);
e = std::move(g);
}
print(d); print(e);
}
int main(void)
{
foo();
int i = 5;
print(i);
{
int r(i);
r *= 123;
print(r);
}
print(i);
}
Not really a wrapper, but the infamous missing copy_if. From here
template<typename In, typename Out, typename Pred>
Out copy_if(In first, In last, Out res, Pred Pr)
{
while (first != last) {
if (Pr(*first)) {
*res++ = *first;
}
++first;
}
return res;
}
template< typename T, std::size_t sz >
inline T* begin(T (&array)[sz]) {return array;}
template< typename T, std::size_t sz >
inline T* end (T (&array)[sz]) {return array + sz;}
Sometimes I feel like I'm in begin() and end() hell. I'd like to have some functions like:
template<typename T>
void sort(T& x)
{
std::sort(x.begin(), x.end());
}
and other similar ones for std::find, std::for_each, and basically all the STL algorithms.
I feel that sort(x) is much quicker to read/understand than sort(x.begin(), x.end()).
I don't use this one nearly as much anymore, but it used to be a staple:
template<typename T>
std::string make_string(const T& data) {
std::ostringstream stream;
stream << data;
return stream.str();
}
Will update with more as I remember them. :P
The utility function in everyones toolbox is of course copy_if. Not really a wrapper though.
Another helper I commonly use is deleter, a functor I use with std::for_each to delete all pointers in a container.
[edit]
Digging through my "sth.h" I also found vector<wstring> StringSplit(wstring const&, wchar_t);
I have a header which puts the following in the "util" namespace:
// does a string contain another string
inline bool contains(const std::string &s1, const std::string &s2) {
return s1.find(s2) != std::string::npos;
}
// remove trailing whitespace
inline std::string &rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// remove leading whitespace
inline std::string &ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// remove whitespace from both ends
inline std::string &trim(std::string &s) {
return ltrim(rtrim(s));
}
// split a string based on a delimeter and return the result (you pass an existing vector for the results)
inline std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
// same as above, but returns a vector for you
inline std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
return split(s, delim, elems);
}
// does a string end with another string
inline bool endswith(const std::string &s, const std::string &ending) {
return ending.length() <= s.length() && s.substr(s.length() - ending.length()) == ending;
}
// does a string begin with another string
inline bool beginswith(const std::string &s, const std::string &start) {
return s.compare(0, start.length(), start) == 0;
}
The infamously missing erase algorithm:
template <
class Container,
class Value
>
void erase(Container& ioContainer, Value const& iValue)
{
ioContainer.erase(
std::remove(ioContainer.begin(),
ioContainer.end(),
iValue),
ioContainer.end());
} // erase
template <
class Container,
class Pred
>
void erase_if(Container& ioContainer, Pred iPred)
{
ioContainer.erase(
std::remove_if(ioContainer.begin(),
ioContainer.end(),
iPred),
ioContainer.end());
} // erase_if
Wrapping sprintf
string example = function("<li value='%d'>Buffer at: 0x%08X</li>", 42, &some_obj);
// 'function' is one of the functions below: Format or stringf
The goal is decoupling formatting from output without getting into trouble with sprintf and its ilk. It's not pretty, but it's very useful, especially if your coding guidelines ban iostreams.
Here is a version which allocates as needed, from Neil Butterworth. [View revision history for Mike's version, which I removed as a subset of the remaining two. It is similar to Neil's, except the latter is exception-safe by using vector instead of delete[]: string's ctor will throw on allocation failure. Mike's also uses the same technique shown later to determine size up front. –RP]
string Format( const char * fmt, ... ) {
const int BUFSIZE = 1024;
int size = BUFSIZE, rv = -1;
vector <char> buf;
do {
buf.resize( size );
va_list valist;
va_start( valist, fmt );
// if _vsnprintf() returns < 0, the buffer wasn't big enough
// so increase buffer size and try again
// NOTE: MSFT's _vsnprintf is different from C99's vsnprintf,
// which returns non-negative on truncation
// http://msdn.microsoft.com/en-us/library/1kt27hek.aspx
rv = _vsnprintf( &buf[0], size, fmt, valist );
va_end( valist );
size *= 2;
}
while( rv < 0 );
return string( &buf[0] );
}
Here is a version which determines the needed size up front, from Roger Pate. This requires writable std::strings, which are provided by popular implementations, but are explicitly required by C++0x. [View revision history for Marcus' version, which I removed as it is slightly different but essentially a subset of the below. –RP]
Implementation
void vinsertf(std::string& s, std::string::iterator it,
char const* fmt, int const chars_needed, va_list args
) {
using namespace std;
int err; // local error code
if (chars_needed < 0) err = errno;
else {
string::size_type const off = it - s.begin(); // save iterator offset
if (it == s.end()) { // append to the end
s.resize(s.size() + chars_needed + 1); // resize, allow snprintf's null
it = s.begin() + off; // iterator was invalidated
err = vsnprintf(&*it, chars_needed + 1, fmt, args);
s.resize(s.size() - 1); // remove snprintf's null
}
else {
char saved = *it; // save char overwritten by snprintf's null
s.insert(it, chars_needed, '\0'); // insert needed space
it = s.begin() + off; // iterator was invalidated
err = vsnprintf(&*it, chars_needed + 1, fmt, args);
*(it + chars_needed) = saved; // restore saved char
}
if (err >= 0) { // success
return;
}
err = errno;
it = s.begin() + off; // above resize might have invalidated 'it'
// (invalidation is unlikely, but allowed)
s.erase(it, it + chars_needed);
}
string what = stringf("vsnprintf: [%d] ", err);
what += strerror(err);
throw runtime_error(what);
}
Public interface
std::string stringf(char const* fmt, ...) {
using namespace std;
string s;
va_list args;
va_start(args, fmt);
int chars_needed = vsnprintf(0, 0, fmt, args);
va_end(args);
va_start(args, fmt);
try {
vinsertf(s, s.end(), fmt, chars_needed, args);
}
catch (...) {
va_end(args);
throw;
}
va_end(args);
return s;
}
// these have nearly identical implementations to stringf above:
std::string& appendf(std::string& s, char const* fmt, ...);
std::string& insertf(std::string& s, std::string::iterator it,
char const* fmt, ...);
The is_sorted utility, to test containers before applying algorithms like include which expect a sorted entry:
template <
class FwdIt
>
bool is_sorted(FwdIt iBegin, FwdIt iEnd)
{
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
return adjacent_find(iBegin, iEnd, std::greater<value_type>()) == iEnd;
} // is_sorted
template <
class FwdIt,
class Pred
>
bool is_sorted_if(FwdIt iBegin, FwdIt iEnd, Pred iPred)
{
if (iBegin == iEnd) return true;
FwdIt aIt = iBegin;
for (++aIt; aIt != iEnd; ++iBegin, ++aIt)
{
if (!iPred(*iBegin, *aIt)) return false;
}
return true;
} // is_sorted_if
Yeah, I know, would be better to negate the predicate and use the predicate version of adjacent_find :)
Definitely boost::addressof
//! \brief Fills reverse_map from map, so that all keys of map
// become values of reverse_map and all values become keys.
//! \note This presumes that there is a one-to-one mapping in map!
template< typename T1, typename T2, class TP1, class TA1, class TP2, class TA2 >
inline void build_reverse_map( const std::map<T1,T2,TP1,TA1>& map
, std::map<T2,T1,TP2,TA2>& reverse_map)
{
typedef std::map<T1,T2,TP1,TA1> map_type;
typedef std::map<T2,T1,TP2,TA2> r_map_type;
typedef typename r_map_type::value_type r_value_type;
for( typename map_type::const_iterator it=map.begin(),
end=map.end(); it!=end; ++it ) {
const r_value_type v(it->second,it->first);
const bool was_new = reverse_map.insert(v).second;
assert(was_new);
}
}
Looking at my stl_util.h, many of the classics (deleter functions, copy_if), and also this one (probably also quite common, but I don't see it given in the responses so far) for searching through a map and returning either the found value or a default, ala get in Python's dict:
template<typename K, typename V>
inline V search_map(const std::map<K, V>& mapping,
const K& key,
const V& null_result = V())
{
typename std::map<K, V>::const_iterator i = mapping.find(key);
if(i == mapping.end())
return null_result;
return i->second;
}
Using the default null_result of a default-constructed V is much as same as the behavior of std::map's operator[], but this is useful when the map is const (common for me), or if the default-constructed V isn't the right thing to use.
Here's my set of extra-utils, built on top of a boost.range'ish std-algo wrapper that you might need for some functions. (that's trivial to write, this is the interesting stuff)
#pragma once
/** #file
#brief Defines various utility classes/functions for handling ranges/function objects
in addition to bsRange (which is a ranged version of the \<algorithm\> header)
Items here uses a STL/boost-style naming due to their 'templatised' nature.
If template variable is R, anything matching range_concept can be used.
If template variable is C, it must be a container object (supporting C::erase())
*/
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/smart_ptr.hpp>
namespace boost
{
struct use_default;
template<class T>
class iterator_range;
#pragma warning(disable: 4348) // redeclaration of template default parameters (this clashes with fwd-decl in boost/transform_iterator.hpp)
template <
class UnaryFunction
, class Iterator
, class Reference = use_default
, class Value = use_default
>
class transform_iterator;
template <
class Iterator
, class Value = use_default
, class Category = use_default
, class Reference = use_default
, class difference = use_default
>
class indirect_iterator;
template<class T>
struct range_iterator;
template <
class Incrementable
, class CategoryOrTraversal = use_default
, class difference = use_default
>
class counting_iterator;
template <class Predicate, class Iterator>
class filter_iterator;
}
namespace orz
{
/// determines if any value that compares equal exists in container
template<class R, class T>
inline bool contains(const R& r, const T& v)
{
return std::find(boost::begin(r), boost::end(r), v) != boost::end(r);
}
/// determines if predicate evaluates to true for any value in container
template<class R, class F>
inline bool contains_if(const R& r, const F& f)
{
return std::find_if(boost::begin(r), boost::end(r), f) != boost::end(r);
}
/// insert elements in range r at end of container c
template<class R, class C>
inline void insert(C& c, const R& r)
{
c.insert(c.end(), boost::begin(r), boost::end(r));
}
/// copy elements that match predicate
template<class I, class O, class P>
inline void copy_if(I i, I end, O& o, const P& p)
{
for (; i != end; ++i) {
if (p(*i)) {
*o = *i;
++o;
}
}
}
/// copy elements that match predicate
template<class R, class O, class P>
inline void copy_if(R& r, O& o, const P& p)
{
copy_if(boost::begin(r), boost::end(r), o, p);
}
/// erases first element that compare equal
template<class C, class T>
inline bool erase_first(C& c, const T& v)
{
typename C::iterator end = boost::end(c);
typename C::iterator i = std::find(boost::begin(c), end, v);
return i != c.end() ? c.erase(i), true : false;
}
/// erases first elements that match predicate
template<class C, class F>
inline bool erase_first_if(C& c, const F& f)
{
typename C::iterator end = boost::end(c);
typename C::iterator i = std::find_if(boost::begin(c), end, f);
return i != end ? c.erase(i), true : false;
}
/// erase all elements (doesn't deallocate memory for std::vector)
template<class C>
inline void erase_all(C& c)
{
c.erase(c.begin(), c.end());
}
/// erase all elements that compare equal
template<typename C, typename T>
int erase(C& c, const T& value)
{
int n = 0;
for (boost::range_iterator<C>::type i = boost::begin(c); i != boost::end(c);) {
if (*i == value) {
i = c.erase(i);
++n;
} else {
++i;
}
}
return n;
}
/// erase all elements that match predicate
template<typename C, typename F>
int erase_if(C& c, const F& f)
{
int n = 0;
for (boost::range_iterator<C>::type i = boost::begin(c); i != boost::end(c);) {
if (f(*i)) {
i = c.erase(i);
++n;
} else {
++i;
}
}
return n;
}
/// erases all consecutive duplicates from container (sort container first to get all)
template<class C>
inline int erase_duplicates(C& c)
{
boost::range_iterator<C>::type i = std::unique(c.begin(), c.end());
typename C::size_type n = std::distance(i, c.end());
c.erase(i, c.end());
return n;
}
/// erases all consecutive duplicates, according to predicate, from container (sort container first to get all)
template<class C, class F>
inline int erase_duplicates_if(C& c, const F& f)
{
boost::range_iterator<C>::type i = std::unique(c.begin(), c.end(), f);
typename C::size_type n = std::distance(i, c.end());
c.erase(i, c.end());
return n;
}
/// fill but for the second value in each pair in range
template<typename R, typename V>
inline void fill_second(R& r, const V& v)
{
boost::range_iterator<R>::type i(boost::begin(r)), end(boost::end(r));
for (; i != end; ++i) {
i->second = v;
}
}
/// applying function to corresponding pair through both ranges, min(r1.size(), r2,size()) applications
template<typename R1, typename R2, typename F>
void for_each2(R1& r1, R2& r2, const F& f)
{
boost::range_iterator<R1>::type i(boost::begin(r1)), i_end(boost::end(r1));
boost::range_iterator<R2>::type j(boost::begin(r2)), j_end(boost::end(r2));
for(;i != i_end && j != j_end; ++i, ++j) {
f(*i, *j);
}
}
/// applying function to corresponding pair through both ranges, min(r1.size(), r2,size()) applications
template<typename R1, typename R2, typename R3, typename F>
void for_each3(R1& r1, R2& r2, R3& r3, const F& f)
{
boost::range_iterator<R1>::type i(boost::begin(r1)), i_end(boost::end(r1));
boost::range_iterator<R2>::type j(boost::begin(r2)), j_end(boost::end(r2));
boost::range_iterator<R3>::type k(boost::begin(r3)), k_end(boost::end(r3));
for(;i != i_end && j != j_end && k != k_end; ++i, ++j, ++k) {
f(*i, *j, *k);
}
}
/// applying function to each possible permutation of objects, r1.size() * r2.size() applications
template<class R1, class R2, class F>
void for_each_permutation(R1 & r1, R2& r2, const F& f)
{
typedef boost::range_iterator<R1>::type R1_iterator;
typedef boost::range_iterator<R2>::type R2_iterator;
R1_iterator end_1 = boost::end(r1);
R2_iterator begin_2 = boost::begin(r2);
R2_iterator end_2 = boost::end(r2);
for(R1_iterator i = boost::begin(r1); i != end_1; ++i) {
for(R2_iterator j = begin_2; j != end_2; ++j) {
f(*i, *j);
}
}
}
template <class R>
inline boost::iterator_range<boost::indirect_iterator<typename boost::range_iterator<R>::type > >
make_indirect_range(R& r)
{
return boost::iterator_range<boost::indirect_iterator<typename boost::range_iterator<R>::type > > (r);
}
template <class R, class F>
inline boost::iterator_range<boost::transform_iterator<F, typename boost::range_iterator<R>::type> >
make_transform_range(R& r, const F& f)
{
return boost::iterator_range<boost::transform_iterator<F, typename boost::range_iterator<R>::type> >(
boost::make_transform_iterator(boost::begin(r), f),
boost::make_transform_iterator(boost::end(r), f));
}
template <class T>
inline boost::iterator_range<boost::counting_iterator<T> >
make_counting_range(T begin, T end)
{
return boost::iterator_range<boost::counting_iterator<T> >(
boost::counting_iterator<T>(begin), boost::counting_iterator<T>(end));
}
template <class R, class F>
inline boost::iterator_range<boost::filter_iterator<F, typename boost::range_iterator<R>::type> >
make_filter_range(R& r, const F& f)
{
return boost::iterator_range<boost::filter_iterator<F, typename boost::range_iterator<R>::type> >(
boost::make_filter_iterator(f, boost::begin(r), boost::end(r)),
boost::make_filter_iterator(f, boost::end(r), boost::end(r)));
}
namespace detail {
template<class T>
T* get_pointer(T& p) {
return &p;
}
}
/// compare member function/variable equal to value. Create using #ref mem_eq() to avoid specfying types
template<class P, class V>
struct mem_eq_type
{
mem_eq_type(const P& p, const V& v) : m_p(p), m_v(v) { }
template<class T>
bool operator()(const T& a) const {
using boost::get_pointer;
using orz::detail::get_pointer;
return (get_pointer(a)->*m_p) == m_v;
}
P m_p;
V m_v;
};
template<class P, class V>
mem_eq_type<P,V> mem_eq(const P& p, const V& v)
{
return mem_eq_type<P,V>(p, v);
}
/// helper macro to define function objects that compare member variables of a class
#define ORZ_COMPARE_MEMBER(NAME, OP) \
template <class P> \
struct NAME##_type \
{ \
NAME##_type(const P&p) : m_p(p) {} \
template<class T> \
bool operator()(const T& a, const T& b) const { \
return (a.*m_p) OP (b.*m_p); \
} \
P m_p; \
}; \
template <class P> \
NAME##_type<P> NAME(const P& p) { return NAME##_type<P>(p); }
#define ORZ_COMPARE_MEMBER_FN(NAME, OP) \
template <class P> \
struct NAME##_type \
{ \
NAME##_type(const P&p) : m_p(p) {} \
template<class T> \
bool operator()(const T& a, const T& b) const { \
return (a.*m_p)() OP (b.*m_p)(); \
} \
P m_p; \
}; \
template <class P> \
NAME##_type<P> NAME(const P& p) { return NAME##_type<P>(p); }
/// helper macro to wrap range functions as function objects (value return)
#define ORZ_RANGE_WRAP_VALUE_2(FUNC, RESULT) \
struct FUNC##_ \
{ \
typedef RESULT result_type; \
template<typename R, typename F> \
inline RESULT operator() (R& r, const F& f) const \
{ \
return FUNC(r, f); \
} \
};
/// helper macro to wrap range functions as function objects (void return)
#define ORZ_RANGE_WRAP_VOID_2(FUNC) \
struct FUNC##_ \
{ \
typedef void result_type; \
template<typename R, typename F> \
inline void operator() (R& r, const F& f) const \
{ \
FUNC(r, f); \
} \
};
/// helper macro to wrap range functions as function objects (void return, one argument)
#define ORZ_RANGE_WRAP_VOID_1(FUNC) \
struct FUNC##_ \
{ \
typedef void result_type; \
template<typename R> \
inline void operator() (R& r) const \
{ \
FUNC(r); \
} \
};
ORZ_RANGE_WRAP_VOID_2(for_each);
ORZ_RANGE_WRAP_VOID_1(erase_all);
ORZ_RANGE_WRAP_VALUE_2(contains, bool);
ORZ_RANGE_WRAP_VALUE_2(contains_if, bool);
ORZ_COMPARE_MEMBER(mem_equal, ==)
ORZ_COMPARE_MEMBER(mem_not_equal, !=)
ORZ_COMPARE_MEMBER(mem_less, <)
ORZ_COMPARE_MEMBER(mem_greater, >)
ORZ_COMPARE_MEMBER(mem_lessequal, <=)
ORZ_COMPARE_MEMBER(mem_greaterequal, >=)
ORZ_COMPARE_MEMBER_FN(mem_equal_fn, ==)
ORZ_COMPARE_MEMBER_FN(mem_not_equal_fn, !=)
ORZ_COMPARE_MEMBER_FN(mem_less_fn, <)
ORZ_COMPARE_MEMBER_FN(mem_greater_fn, >)
ORZ_COMPARE_MEMBER_FN(mem_lessequal_fn, <=)
ORZ_COMPARE_MEMBER_FN(mem_greaterequal_fn, >=)
#undef ORZ_COMPARE_MEMBER
#undef ORZ_RANGE_WRAP_VALUE_2
#undef ORZ_RANGE_WRAP_VOID_1
#undef ORZ_RANGE_WRAP_VOID_2
}
I seem to need a Cartesian product, for example {A, B}, {1, 2} -> {(A,1), (A,2), (B,1), (B,2)}
// OutIt needs to be an iterator to a container of std::pair<Type1, Type2>
template <typename InIt1, typename InIt2, typename OutIt>
OutIt
cartesian_product(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt out)
{
for (; first1 != last1; ++first1)
for (InIt2 it = first2; it != last2; ++it)
*out++ = std::make_pair(*first1, *it);
return out;
}
I would call such an append function by its name and would use operator+= , operator*= and so on for element-wise operations, such as:
template<typename X> inline void operator+= (std::vector<X>& vec1, const X& value)
{
std::transform( vec1.begin(), vec1.end(), vec1.begin(), std::bind2nd(std::plus<X>(),value) );
}
template<typename X> inline void operator+= (std::vector<X>& vec1, const std::vector<X>& vec2)
{
std::transform( vec1.begin(), vec1.end(), vec2.begin(), vec1.begin(), std::plus<X>() );
}
some other simple and obvious wrappers as implied before:
template<typename X> inline void sort_and_unique(std::vector<X> &vec)
{
std::sort( vec.begin(), vec.end() );
vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() );
}
template<typename X> inline void clear_vec(std::vector<X> &vec)
{
std::vector<X>().swap(vec);
}
template<typename X> inline void trim_vec(std::vector<X> &vec, std::size_t new_size)
{
if (new_size<vec.size())
std::vector<X>(vec.begin(),vec.begin() + new_size).swap(vec);
else
std::vector<X>(vec).swap(vec);
}
Insert a new item and return it, useful for simple move semantics like push_back(c).swap(value) and related cases.
template<class C>
typename C::value_type& push_front(C& container) {
container.push_front(typename C::value_type());
return container.front();
}
template<class C>
typename C::value_type& push_back(C& container) {
container.push_back(typename C::value_type());
return container.back();
}
template<class C>
typename C::value_type& push_top(C& container) {
container.push(typename C::value_type());
return container.top();
}
Pop and return an item:
template<class C>
typename C::value_type pop_front(C& container) {
typename C::value_type copy (container.front());
container.pop_front();
return copy;
}
template<class C>
typename C::value_type pop_back(C& container) {
typename C::value_type copy (container.back());
container.pop_back();
return copy;
}
template<class C>
typename C::value_type pop_top(C& container) {
typename C::value_type copy (container.top());
container.pop();
return copy;
}
IMO there needs to be more functionality for pair:
#ifndef pair_iterator_h_
#define pair_iterator_h_
#include <boost/iterator/transform_iterator.hpp>
#include <functional>
#include <utility>
// pair<T1, T2> -> T1
template <typename PairType>
struct PairGetFirst : public std::unary_function<PairType, typename PairType::first_type>
{
typename typename PairType::first_type& operator()(PairType& arg) const
{ return arg.first; }
const typename PairType::first_type& operator()(const PairType& arg) const
{ return arg.first; }
};
// pair<T1, T2> -> T2
template <typename PairType>
struct PairGetSecond : public std::unary_function<PairType, typename PairType::second_type>
{
typename PairType::second_type& operator()(PairType& arg) const
{ return arg.second; }
const typename PairType::second_type& operator()(const PairType& arg) const
{ return arg.second; }
};
// iterator over pair<T1, T2> -> iterator over T1
template <typename Iter>
boost::transform_iterator<PairGetFirst<typename std::iterator_traits<Iter>::value_type>, Iter>
make_first_iterator(Iter i)
{
return boost::make_transform_iterator(i,
PairGetFirst<typename std::iterator_traits<Iter>::value_type>());
}
// iterator over pair<T1, T2> -> iterator over T2
template <typename Iter>
boost::transform_iterator<PairGetSecond<typename std::iterator_traits<Iter>::value_type>, Iter>
make_second_iterator(Iter i)
{
return boost::make_transform_iterator(i,
PairGetSecond<typename std::iterator_traits<Iter>::value_type>());
}
// T1 -> pair<T1, T2>
template <typename FirstType, typename SecondType>
class InsertIntoPair1st : public std::unary_function<FirstType, std::pair<FirstType, SecondType> >
{
public:
InsertIntoPair1st(const SecondType& second_element) : second_(second_element) {}
result_type operator()(const FirstType& first_element)
{
return result_type(first_element, second_);
}
private:
SecondType second_;
};
// T2 -> pair<T1, T2>
template <typename FirstType, typename SecondType>
class InsertIntoPair2nd : public std::unary_function<SecondType, std::pair<FirstType, SecondType> >
{
public:
InsertIntoPair2nd(const FirstType& first_element) : first_(first_element) {}
result_type operator()(const SecondType& second_element)
{
return result_type(first_, second_element);
}
private:
FirstType first_;
};
#endif // pair_iterator_h_
template <typename T> size_t bytesize(std::vector<T> const& v) { return sizeof(T) * v.size(); }
If you need to use a lot of functions that take pointer + number of bytes, it's always just
fun(vec.data(), bytesize(vec));
Duplicate a string with *:
std::string operator*(std::string s, size_t n)
{
std::stringstream ss;
for (size_t i=0; i<n; i++) ss << s;
return ss.str();
}
One of my favorite is the Transposer that finds a transpose of a tuple of containers of the same size. That is, if you have a tuple<vector<int>,vector<float>>, it converts it into a vector<tuple<int, float>>. Comes handy in XML programming. Here is how I did it.
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
#include <algorithm>
#include <stdexcept>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/type_traits.hpp>
using namespace boost;
template <class TupleOfVectors>
struct GetTransposeTuple;
template <>
struct GetTransposeTuple<tuples::null_type>
{
typedef tuples::null_type type;
};
template <class TupleOfVectors>
struct GetTransposeTuple
{
typedef typename TupleOfVectors::head_type Head;
typedef typename TupleOfVectors::tail_type Tail;
typedef typename
tuples::cons<typename remove_reference<Head>::type::value_type,
typename GetTransposeTuple<Tail>::type> type;
};
template <class TupleOfVectors,
class ValueTypeTuple =
typename GetTransposeTuple<TupleOfVectors>::type,
unsigned int TUPLE_INDEX = 0>
struct Transposer
: Transposer <typename TupleOfVectors::tail_type,
ValueTypeTuple,
TUPLE_INDEX + 1>
{
typedef typename remove_reference<typename TupleOfVectors::head_type>::type
HeadContainer;
typedef typename TupleOfVectors::tail_type Tail;
typedef Transposer<Tail, ValueTypeTuple, TUPLE_INDEX + 1> super;
typedef std::vector<ValueTypeTuple> Transpose;
Transposer(TupleOfVectors const & tuple)
: super(tuple.get_tail()),
head_container_(tuple.get_head()),
head_iter_(head_container_.begin())
{}
Transpose get_transpose ()
{
Transpose tran;
tran.reserve(head_container_.size());
for(typename HeadContainer::const_iterator iter = head_container_.begin();
iter != head_container_.end();
++iter)
{
ValueTypeTuple vtuple;
this->populate_tuple(vtuple);
tran.push_back(vtuple);
}
return tran;
}
private:
HeadContainer const & head_container_;
typename HeadContainer::const_iterator head_iter_;
protected:
void populate_tuple(ValueTypeTuple & vtuple)
{
if(head_iter_ == head_container_.end())
throw std::runtime_error("Container bound exceeded.");
else
{
vtuple.get<TUPLE_INDEX>() = *head_iter_++;
super::populate_tuple (vtuple);
}
}
};
template <class ValueTypeTuple,
unsigned int INDEX>
struct Transposer <tuples::null_type, ValueTypeTuple, INDEX>
{
void populate_tuple(ValueTypeTuple &) {}
Transposer (tuples::null_type const &) {}
};
template <class TupleOfVectors>
typename Transposer<TupleOfVectors>::Transpose
transpose (TupleOfVectors const & tupleofv)
{
return Transposer<TupleOfVectors>(tupleofv).get_transpose();
}
int main (void)
{
typedef std::vector<int> Vint;
typedef std::list<float> Lfloat;
typedef std::vector<long> Vlong;
Vint vint;
Lfloat lfloat;
Vlong vlong;
std::generate_n(std::back_inserter(vint), 10, rand);
std::generate_n(std::back_inserter(lfloat), 10, rand);
std::generate_n(std::back_inserter(vlong), 10, rand);
typedef tuples::tuple<Vint, Lfloat, Vlong> TupleOfV;
typedef GetTransposeTuple<TupleOfV>::type TransposeTuple;
Transposer<TupleOfV>::Transpose tran =
transpose(make_tuple(vint, lfloat, vlong));
// Or alternatively to avoid copying
// transpose(make_tuple(ref(vint), ref(lfloat), ref(vlong)));
std::copy(tran.begin(), tran.end(),
std::ostream_iterator<TransposeTuple>(std::cout, "\n"));
return 0;
}
Not sure if these qualify as std wrappers, but my commonly used helper functions are:
void split(string s, vector<string> parts, string delims);
string join(vector<string>& parts, string delim);
int find(T& array, const V& value);
void assert(bool condition, string message);
V clamp(V value, V minvalue, V maxvalue);
string replace(string s, string from, string to);
const char* stristr(const char* a,const char*b);
string trim(string str);
T::value_type& dyn(T& array,int index);
T and V here are template arguments. The last function works the same way as []-operator, but with automating resizing to fit needed index.
Similar to what people posted before, I have convenience overloads of algorithms for simplifying passing iterator arguments. I call algorithms like this:
for_each(iseq(vec), do_it());
I overloaded all the algorithms such that they take a single parameter of type input_sequence_range<> instead of the two input iterators (input as in anything that isn't mere output).
template<typename In>
struct input_sequence_range
: public std::pair<In,In>
{
input_sequence_range(In first, In last)
: std::pair<In,In>(first, last)
{ }
};
And this is how iseq() works:
template<typename C>
input_sequence_range<typename C::const_iterator> iseq(const C& c)
{
return input_sequence_range<typename C::const_iterator>(c.begin(),
c.end());
}
Similarly, I have specializations for
const_iterators
pointers (primitive arrays)
stream iterators
any range [begin,end) just for a uniform use: use iseq() for everything
Unordered erase for std::vector. The most efficient way to erase an element from a vector but it does not preserve the order of elements. I didn't see the point of extending it to other containers since most don't have the same penalty for removing items from the middle. It's similar to some other templates already posted but it uses std::swap to move items instead of copying.
template<typename T>
void unordered_erase(std::vector<T>& vec, const typename std::vector<T>::iterator& it)
{
if (it != vec.end()) // if vec is empty, begin() == end()
{
std::swap(vec.back(), *it);
vec.pop_back();
}
}
Signum returns the sign of a type. Returns -1 for negative, 0 for zero and 1 for positive.
template <typename T>
int signum(T val)
{
return (val > T(0)) - (val < T(0));
}
Clamp is pretty self explanatory, it clamps a value so that it lies within the given range. It boggles my mind that the Standard Library includes min and max but not clamp
template<typename T>
T clamp(const T& value, const T& lower, const T& upper)
{
return value < lower ? lower : (value > upper ? upper : value);
}

How to slice with for-range loop ? C++0x

Using range based for loops in C++0X, I know we'll be able to do :
std::vector<int> numbers = generateNumbers();
for( int k : numbers )
{
processNumber( k );
}
(might be even simpler to write with lambda)
But how should i do if I only want to apply processNumber( k ) to a part of numbers? For example, how should I write this for loop for to apply processNumber() to the half (head or tail) of the numbers? Is "slicing" allowed like in Python or Ruby?
You can use the "sliced" range adaptor from the Boost.Range library:
#include <boost/range/adaptor/sliced.hpp>
using boost::adaptors::sliced;
...
std::vector<int> numbers = generateNumbers();
for( int k : numbers | sliced(0, numbers.size() / 2))
{
processNumber( k );
}
One possibility might be boost's iterator_range
(Not having a compiler which supports range-based for, using BOOST_FOREACH instead. I'd expect range-based for work the same, as long as the container or range has the begin and end method.)
#include <boost/foreach.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
BOOST_FOREACH(int n, boost::make_iterator_range(v.begin(), v.begin() + v.size() / 2)) {
std::cout << n << '\n';
}
}
For convenience you could also make your own slice function, so it would accept indices instead of iterators. Again, it could be based on boost.iterator_range, or not:
#include <cstddef>
#include <iterator>
template <class Iterator>
class iter_pair
{
public:
typedef Iterator iterator;
typedef Iterator const_iterator; //BOOST_FOREACH appears to want this
iter_pair(iterator first, iterator last): first(first), last(last) {}
iterator begin() const { return first; }
iterator end() const { return last; }
private:
iterator first, last;
};
template <class Container>
struct iterator_type
{
typedef typename Container::iterator type;
};
template <class Container>
struct iterator_type<const Container>
{
typedef typename Container::const_iterator type;
};
template <class Container>
iter_pair<typename iterator_type<Container>::type>
slice(Container& c, size_t i_first, size_t i_last)
{
typedef typename iterator_type<Container>::type iterator;
iterator first = c.begin();
std::advance(first, i_first);
iterator last = first;
std::advance(last, i_last - i_first);
return iter_pair<iterator>(first, last);
}
template <class Container>
iter_pair<typename iterator_type<Container>::type>
slice(Container& c, size_t i_last)
{
return slice(c, 0, i_last);
}
//could probably also be overloaded for arrays
#include <cctype>
#include <string>
#include <boost/foreach.hpp>
#include <iostream>
int main()
{
std::string s("Hello world, la-la-la!");
BOOST_FOREACH( char& c, slice(s, 2, 11)) {
if (c == 'l')
c = std::toupper(c);
}
const std::string& r = s;
BOOST_FOREACH( char c, slice(r, r.size() - 1) ) {
std::cout << c << " ";
}
std::cout << '\n';
}
Generally one would probably be working with iterators in the first place, so it might not be that useful.
Something like this may work (unchecked as I don't have access to a C++0x compiler),
Edit: Checked it on VS10, of course I had to fix numurous errors....
Define a class which is a proxy to any container and whose iterators only return a subset of the container. The example I supply is the simplest one giving the first half but it can be made much more general.
template <class Container>
class head_t {
Container& c_;
public:
template <class T>
class iter {
T curr_;
const T& end_;
int limit_; // count how many items iterated
public:
iter(T curr, const T& end)
: curr_(curr)
, end_(end)
, limit_(std::distance(curr_, end_)/2)
{ }
typename Container::value_type operator*() { return *curr_; }
// Do the equivilant for for operator++(int)
iter& operator++() {
if (--limit_ == 0) // finished our slice
curr_ = end_;
else
++curr_;
return *this;
}
bool operator!=(const iter& i) const {
return curr_ != i.curr_;
}
};
head_t(Container& c) : c_(c) {}
iter<typename Container::iterator> begin() {
return iter<typename Container::iterator>(c_.begin(), c_.end());
}
iter<typename Container::iterator> end() {
return iter<typename Container::iterator>(c_.end(), c_.end());
}
};
template <class T>
head_t<T> head(T& t) { return head_t<T>(t); }
And then you use it in the loop:
for( int k : head(numbers) )