How do you pass a template name to a method? - c++

Lets say I have two template functions for iterating through a container:
template <typename I, typename C>
It Prev(I i, const C& c) noexcept {
Expects(i != c.end());
if (i == c.begin()) return c.end();
return i - 1;
}
and
template <typename I, typename C>
It Next(I i, const C& c) noexcept {
Expects(i != c.end());
return i + 1;
}
And a class with a GetNextElement and GetPrevElement that use these templates:
struct MyClass {
std::vector<int> elements;
int* GetNextElement(std::vector<int>::iterator i) {
auto next = Next(i, elements);
if (next == elements.end()) return nullptr;
return &*it;
}
int* GetPrevElement(std::vector<int>::iterator i) {
auto prev = Prev(i, elements);
if (prev == elements.end()) return nullptr;
return &*it;
}
};
These two methods do the same thing, except for calling a different template. How do I turn these into a single member function that might be called like
MyClass mc;
// ...
auto it = mc.elements.begin();
auto next = mc.GetElement<Next>(it);
// Or maybe mc.GetElement(it, Next);

#define OINVOKE(...) __VA_ARGS__(decltype(args)(args)...)
#define OVERLOADS_OF(...) [](auto&&...args)\
noexcept(noexcept(OINVOKE(__VA_ARGS__)))\
->decltype(OINVOKE(__VA_ARGS__))\
{ return OINVOKE(__VA_ARGS__); }
auto fNext=OVERLOADS_OF(Next);
auto fPrev=OVERLOADS_OF(Prev);
Then:
template<auto* pf>
int* GetElement(std::vector<int>::iterator i) {
auto next = (*pf)(i, elements);
if (next == elements.end()) return nullptr;
return &*it;
}
auto it = mc.elements.begin();
auto next = GetElement<&fNext>(it);
requires C++17.

This problem is greatly simplified if you can wrap your functions in struct.
struct Prev
{
template <typename I, typename C>
I operator()(I i, const C& c) noexcept {
Expects(i != c.end());
if (i == c.begin()) return c.end();
return i - 1;
}
};
struct Next
{
template <typename I, typename C>
I operator()(I i, const C& c) noexcept {
Expects(i != c.end());
return i + 1;
}
};
You can then simply pass them as template arguments.
struct MyClass
{
public:
auto begin() { return elements.begin(); }
auto end() { return elements.end(); }
template<typename T, typename I>
I GetElement(I iter)
{
return T()(iter, this->elements);
}
private:
std::vector<int> elements;
};
int main()
{
MyClass mc;
auto it = mc.begin();
auto next = mc.GetElement<Next>(it);
auto prev = mc.GetElement<Prev>(it);
}

You can try this code:
template <std::vector<int>::iterator (*FOO)(std::vector<int>::iterator, const std::vector<int>&)>
std::vector<int>::iterator GetElement(std::vector<int>::iterator i)
{
return FOO(i, elements);
}

Related

Raw loops vs. algorithm for loops that depend on the index

I'm working on big codes for which performance matters. And one of the things I read is that raw loops should be avoided and replaced by for_each, range-based for loops, or STL algorithms etc etc. The problem is that in all (most) examples, everything looks adapted for the problem, i.e. for_each is shown with the cout routine *eye roll*.
In my case, the index inside the loop matters (unless you show me otherwise). For example, I want to create tables like this:
std::vector<double> vect1 (nmax), vect2 (nmax);
for (size_t i{0}; i < nmax; ++i) {
vect1[i] = f(i); // f is a routine defined somewhere else
vect2[i] = f(i)+2.0;
}
What I could use is the generate function with a lambda function and it would be something like this:
std::vector<double> vect1 (nmax), vect2 (nmax);
size_t count{0};
generate(vect1.begin(), vect1.end(), [&]() {return f(count++);});
count=0;
generate(vect2.begin(), vect2.end(), [&]() {return f(count++) + 2.0;});
But I’m not a big fan of that, because:
count exists until the end of the routine.
We see that with another function, I have to put back count to zero and generate another vector again. I have to track down all the count variables etc. With the for loop, I could just put it in the same loop.
With the for loop, the correspondence is seen easily. i is on the left and the right. With generate, I feel like it’s counting with a different variable on the left and the right, which means potential mistake.
I can only do count++, not ++count, which means copy of variables.
Of course, this is a simple example. But I would like to know if the generate() version is still better for this kind of things (code/performance/readability wise). Or maybe there’s a better way of doing it, and I’m open to all suggestions and comments.
Thanks!
I wrote an index range that lets me:
std::vector<double> vect1 (nmax), vect2 (nmax);
for (auto i : index_upto(nmax))
vect1[i] = f(i); // f is a routine defined somewhere else
vect2[i] = f(i)+2.0;
}
which eliminates the manual fenceposting but leaves the code otherwise unchanged.
This isn't all that hard. Write a pseudo-iterator that stores a T and returns a copy on unary *. It should support == and ++ (passing both into the stored T).
template<class T>
struct index_it {
T t;
index_it& operator++() { ++t; return *this; }
index_it operator++(int) { auto r = *this; ++*this; return r; }
friend bool operator==( index_it const& lhs, index_it const& rhs ) {
return lhs.t == rhs.t;
}
friend bool operator!=( index_it const& lhs, index_it const& rhs ) {
return lhs.t != rhs.t;
}
T operator*()const& { return t; }
T operator*()&& { return std::move(t); }
};
Next, write a range:
template<class It>
struct range {
It b, e;
It begin() const { return b; }
It end() const { return e; }
};
then compose the two.
template<class T>
using index_range = range<index_it<T>>;
template<class T>
index_range<T> make_index_range( T s, T f ) {
return {{std::move(s)}, {std::move(f)}};
}
index_range<std::size_t> index_upto( std::size_t n ) {
return make_index_range( std::size_t(0), n );
}
note that index_it is not an iterator, but works much like one. You could probably finish it and make it an input iterator; beyond that you run into problems as iterators expect backing containers.
Using a stateful lambda is not a good idea. You may be better off writing your own generate function that takes a function object receiving an iterator:
template<class ForwardIt, class Generator>
void generate_iter(ForwardIt first, ForwardIt last, Generator g) {
while (first != last) {
*first = g(first);
++first;
}
}
You can use it as follows:
generate_iter(vect1.begin(), vect1.end(), [&](const std::vector<double>::iterator& iter) {
auto count = std::distance(vect1.begin(), iter);
return f(count);
});
Demo.
We could use a mutable lambda...
#include <vector>
#include <algorithm>
double f(int x) { return x*2; }
int main()
{
constexpr int nmax = 100;
std::vector<double> vect1 (nmax), vect2 (nmax);
std::generate(vect1.begin(),
vect1.end(),
[count = int(0)]() mutable { return f(count++); });
std::generate(vect2.begin(),
vect2.end(),
[count = int(0)]() mutable { return f(count++) + 2.0; });
}
Another option (uses c++17 for template argument deduction):
template<class F>
struct counted_function
{
constexpr counted_function(F f, int start = 0, int step = 1)
: f(f)
, counter(start)
, step(step) {}
decltype(auto) operator()() {
return f(counter++);
}
F f;
int counter;
int step;
};
used as:
std::generate(vect2.begin(),
vect2.end(),
counted_function([](auto x) { return f(x) + 2.0; }));
And finally, just for fun, could write this:
generate(vect2).invoking(f).with(every<int>::from(0).to(nmax - 1));
...if we had written something like this...
#include <vector>
#include <algorithm>
#include <iterator>
double f(int x) { return x*2; }
template<class T> struct value_iter
{
using value_type = T;
using difference_type = T;
using reference = T&;
using pointer = T*;
using iterator_category = std::forward_iterator_tag;
friend bool operator==(value_iter l, value_iter r)
{
return l.current == r.current;
}
friend bool operator!=(value_iter l, value_iter r)
{
return !(l == r);
}
T const& operator*() const& { return current; }
value_iter& operator++() { ++current; return *this; }
T current;
};
template<class T> struct every
{
struct from_thing
{
T from;
struct to_thing
{
auto begin() const { return value_iter<T> { from };}
auto end() const { return value_iter<T> { to+1 };}
T from, to;
};
auto to(T x) { return to_thing { from, x }; }
};
static constexpr auto from(T start)
{
return from_thing { start };
}
};
template<class F>
struct counted_function
{
constexpr counted_function(F f, int start = 0, int step = 1)
: f(f)
, counter(start)
, step(step) {}
decltype(auto) operator()() {
return f(counter++);
}
F f;
int counter;
int step;
};
template <class Container> struct generate
{
generate(Container& c) : c(c) {}
template<class F>
struct invoking_thing
{
template<class Thing>
auto with(Thing thing)
{
using std::begin;
using std::end;
std::copy(begin(thing), end(thing), begin(c));
return c;
}
F f;
Container& c;
};
template<class F>
auto invoking(F f) { return invoking_thing<F>{f, c}; }
Container& c;
};
int main()
{
constexpr int nmax = 100;
std::vector<double> vect2 (nmax);
generate(vect2).invoking(f).with(every<int>::from(0).to(nmax - 1));
}
With range-v3, it would be something like:
auto vect1 = ranges::view::ints(0, nmax) | ranges::view::transform(f);
auto vect2 = ranges::view::ints(0, nmax) | ranges::view::transform(f2);
// or auto vect2 = vect1 | ranges::view::transform([](double d){ return d + 2.; });
Demo

Can I avoid template recursion here?

I've written a for_each for tuples:
template <typename Tuple, typename F, size_t begin, size_t end>
enable_if_t<begin == end || tuple_size<Tuple>::value < end> for_each(Tuple&, F&&) {
}
template <typename Tuple, typename F, size_t begin = 0U, size_t end = tuple_size<Tuple>::value>
enable_if_t<begin < end && tuple_size<Tuple>::value >= end> for_each(Tuple& t, F&& f) {
f(get<begin>(t));
for_each<Tuple, F, begin + 1, end>(t, forward<F>(f));
}
[Live Example]
But Yakk's answer to this question gives a wonderful example of how to handle running a lambda on all tuple values non-recursively:
namespace detail {
template<class F, class...Args>
void for_each_arg(F&& f, Args&&...args) {
using detail = int[];
static_cast<void>(detail{((f(std::forward<Args>(args))), void(), 0)..., 0});
}
}
template <typename F, typename Tuple>
void for_each_tuple_element(F&& f, Tuple&& t) {
return experimental::apply([&](auto&&...args) { detail::for_each_arg(forward<F>(f), decltype(args)(args)... ); }, forward<Tuple>(t));
}
This requires apply. You can see my simplification of Yakk's answer here: http://ideone.com/yAYjmw
My question is this: Is there a way to somehow retrofit for_each_tuple_element with a range, avoiding the recursion that my code incurs? I've tried constructing the subset of the tuple defined by the range, but I can't seem to do that without using recursion, and then why not just my for_each?
You could avoid recursion by generating a sequence of calls to the std::get<Is>(t)... function, with Is indices ranging from begin up to end-1. It's fairly easy to generate a sequence of consecutive numbers starting at a given index, as it's enough to make the starting point an offset that is then added to each item of a regular index sequence, e.g.:
std::get<begin + 0>(t), std::get<begin + 1>(t), ... std::get<begin + n>(t)
where the length of the sequence is equal to the distance between begin and end.
#include <tuple>
#include <type_traits>
#include <utility>
#include <cstddef>
#include <limits>
template <std::size_t begin, typename Tuple, typename F, std::size_t... Is>
void for_each(Tuple&& t, F&& f, std::index_sequence<Is...>)
{
using expand = int[];
static_cast<void>(expand{ 0, (f(std::get<begin + Is>(std::forward<Tuple>(t))), void(), 0)... });
}
template <std::size_t begin = 0U, std::size_t end = std::numeric_limits<std::size_t>::max(), typename Tuple, typename F>
void for_each(Tuple&& t, F&& f)
{
for_each<begin>(std::forward<Tuple>(t), std::forward<F>(f)
, std::make_index_sequence<(end==std::numeric_limits<std::size_t>::max()?std::tuple_size<std::decay_t<Tuple>>::value:end)-begin>{});
}
Test:
int main()
{
auto t = std::make_tuple(3.14, "Hello World!", -1);
auto f = [](const auto& i) { std::cout << i << ' '; };
for_each<1>(t, f);
for_each<1,3>(t, f);
for_each<0,2>(t, f);
}
DEMO
Also, note that defaulted template parameters of a function template don't have to be placed at the end of a template parameter list, hence, you can avoid the ugly decltype(t), decltype(f) part. This implies that end cannot be defaulted to std::tuple_size<Tuple>::value (since Tuple goes after end), but at this point all you need is some default magic number.
You could implement a make_index_range metafunction like so:
template <std::size_t Start, std::size_t End>
struct index_range {
template <std::size_t... Idx>
static std::index_sequence<(Idx + Start)...>
make_range (std::index_sequence<Idx...>);
using type = decltype(make_range(std::make_index_sequence<End-Start>{}));
};
template <std::size_t Start, std::size_t End>
using make_index_range = typename index_range<Start, End>::type;
Then you can use this to generate your std::index_sequence:
template <typename Tuple, typename F, std::size_t... Idx>
void for_each(Tuple& t, F&& f, std::index_sequence<Idx...>) {
(void)std::initializer_list<int> {
(std::forward<F>(f)(std::get<Idx>(t)), 0)...
};
}
template <typename Tuple, size_t begin = 0U,
size_t end = tuple_size<Tuple>::value, typename F>
enable_if_t<begin < end && tuple_size<Tuple>::value >= end>
for_each(Tuple& t, F&& f) {
for_each(t, std::forward<F>(f), make_index_range<begin, end>{});
}
You would use this like so:
auto t = std::make_tuple(1, 42.1, "hello world");
for_each<decltype(t), 2, 3>(t,[](auto e){std::cout << e << '\n';});
//outputs hello world
Note that you need to pass decltype(t) in if you want to give a begin and end. You could avoid that by using the technique in Peter Skotnicki's answer.
Live Demo
Inspired by #Piotr, but with extra prettiness :-)
#include <tuple>
#include <utility>
#include <tuple>
#include <cstddef>
#include <string>
#include <iostream>
template<class Tuple, size_t I>
struct tuple_iterator
{
constexpr tuple_iterator(Tuple& p) : _p(p) {}
static constexpr auto index() { return I; }
constexpr auto operator++() const { return tuple_iterator<Tuple, I+1>(_p); }
constexpr auto operator--() const { return tuple_iterator<Tuple, I-1>(_p); }
constexpr decltype(auto) deref() const { return _p; }
Tuple& _p;
};
template<class...Ts>
constexpr auto begin(const std::tuple<Ts...>& t) {
return tuple_iterator<const std::tuple<Ts...>, 0>(t);
}
template<class...Ts>
constexpr auto end(const std::tuple<Ts...>& t) {
return tuple_iterator<const std::tuple<Ts...>, sizeof...(Ts)>(t);
}
template<class Tuple, size_t I>
constexpr auto prev(tuple_iterator<Tuple, I> it) { return --it; }
template<class Tuple, size_t I>
constexpr auto next(tuple_iterator<Tuple, I> it) { return ++it; }
namespace detail
{
template <
std::size_t begin,
typename Tuple,
typename F,
std::size_t... Is
>
void for_each(Tuple&& t, F&& f, std::index_sequence<Is...>)
{
using expand = int[];
static_cast<void>(expand{ 0, (f(std::get<begin + Is>(std::forward<Tuple>(t))), void(), 0)... });
}
}
template<class Tuple, size_t First, size_t Last, class Func>
void for_each(tuple_iterator<Tuple, First> first, tuple_iterator<Tuple, Last> last, Func&& f)
{
constexpr auto dist = Last - First;
constexpr auto base = First;
constexpr auto extent = std::make_index_sequence<dist>();
detail::for_each<base>(first.deref(), std::forward<Func>(f), extent);
}
int main()
{
using namespace std;
auto x = make_tuple("dont print me", 1, "two", "three"s, "or me");
for_each(next(begin(x)), prev(end(x)), [](const auto& x) { cout << x << endl; });
return 0;
}
expected results:
1
two
three
Sorry about the second answer, but I felt that this was worth it.
Presenting the function make_poly_tuple_iterator() which returns an iterator that will iterate over elements in a tuple, working with all algorithms in the std namespace.
de-referencing the iterator results in a boost::variant< reference types... > so the functors will have to be specialisations of boost::static_visitor<>.
Demo below, use like this:
int main()
{
using namespace std;
auto x = make_tuple(tagged_string<tag1>("dont print me"),
1,
2.0,
tagged_string<tag2>("three"),
tagged_string<tag3>("or me"));
// this is the statically typed version
for_each(next(begin(x)),
prev(end(x)),
[](const auto& x) { cout << x << endl; });
// and the polymorphic version
auto first = std::next(make_poly_tuple_iterator(begin(x)));
auto last = std::prev(make_poly_tuple_iterator(end(x)));
// note: std::for_each ;-)
std::for_each(first, last, print_it());
return 0;
}
expected results:
1
2
three
printing: 1
printing: 2
printing: three
Complete code:
Yes I know, there are many, many improvements that can be made....
#include <tuple>
#include <utility>
#include <tuple>
#include <cstddef>
#include <string>
#include <iostream>
#include <boost/variant.hpp>
#include <stdexcept>
#include <exception>
template<class Tuple, size_t I>
struct tuple_iterator
{
constexpr tuple_iterator(Tuple& p) : _p(p) {}
static constexpr auto index() { return I; }
static constexpr auto upper_bound() { return std::tuple_size<Tuple>::value; }
static constexpr auto lower_bound() { return 0; }
template<size_t I2> static constexpr auto ValidIndex = I2 >= lower_bound() && I2 < upper_bound();
template<size_t I2, typename = void>
struct de_ref_type { using type = decltype(std::get<0>(std::declval<Tuple>())); };
template<size_t I2>
struct de_ref_type<I2, std::enable_if_t<ValidIndex<I2>>>
{ using type = decltype(std::get<I2>(std::declval<Tuple>())); };
template<size_t I2> using DerefType = typename de_ref_type<I2>::type;
constexpr auto operator++() const { return make_like_me<I+1>(); }
constexpr auto operator--() const { return make_like_me<I-1>(); }
template<size_t I2, std::enable_if_t<(I2 < lower_bound())>* = nullptr>
constexpr auto make_like_me() const { return tuple_iterator<Tuple, lower_bound()>(_p); }
template<size_t I2, std::enable_if_t<(I2 >= upper_bound())>* = nullptr>
constexpr auto make_like_me() const { return tuple_iterator<Tuple, upper_bound()>(_p); }
template<size_t I2, std::enable_if_t<ValidIndex<I2>>* = nullptr>
constexpr auto make_like_me() const { return tuple_iterator<Tuple, I2>(_p); }
constexpr decltype(auto) deref() const { return _p; }
template<size_t X> bool operator==(const tuple_iterator<Tuple, X>& r) const { return false; }
bool operator==(const tuple_iterator<Tuple, I>& r) const {
return std::addressof(_p) == std::addressof(r._p);
}
template<size_t I2, std::enable_if_t<ValidIndex<I2>>* =nullptr>
DerefType<I2> impl_star() const { return std::get<I2>(_p); }
template<size_t I2, std::enable_if_t<not ValidIndex<I2>>* =nullptr>
DerefType<I2> impl_star() const
{ throw std::logic_error("out of range"); }
decltype(auto) operator*() const {
return impl_star<index()>();
}
Tuple& _p;
};
template<class...Ts>
constexpr auto begin(const std::tuple<Ts...>& t) {
return tuple_iterator<const std::tuple<Ts...>, 0>(t);
}
template<class...Ts>
constexpr auto end(const std::tuple<Ts...>& t) {
return tuple_iterator<const std::tuple<Ts...>, sizeof...(Ts)>(t);
}
template<class Tuple, size_t I>
constexpr auto prev(tuple_iterator<Tuple, I> it) { return --it; }
template<class Tuple, size_t I>
constexpr auto next(tuple_iterator<Tuple, I> it) { return ++it; }
namespace detail
{
template <
std::size_t begin,
typename Tuple,
typename F,
std::size_t... Is
>
void for_each(Tuple&& t, F&& f, std::index_sequence<Is...>)
{
using expand = int[];
static_cast<void>(expand{ 0, (f(std::get<begin + Is>(std::forward<Tuple>(t))), void(), 0)... });
}
}
template<class Tuple, size_t First, size_t Last, class Func>
void for_each(tuple_iterator<Tuple, First> first, tuple_iterator<Tuple, Last> last, Func&& f)
{
constexpr auto dist = Last - First;
constexpr auto base = First;
constexpr auto extent = std::make_index_sequence<dist>();
detail::for_each<base>(first.deref(), std::forward<Func>(f), extent);
}
namespace detail {
template<class Tuple>
struct variant_of_tuple;
template<class...Ts>
struct variant_of_tuple<std::tuple<Ts...>>
{
// todo: some work to remove duplicates
using type = boost::variant<std::add_lvalue_reference_t<Ts>...>;
};
template<class...Ts>
struct variant_of_tuple<const std::tuple<Ts...>>
{
// todo: some work to remove duplicates
using type = boost::variant<std::add_lvalue_reference_t<std::add_const_t<Ts>>...>;
};
}
template<class Tuple>
using ToVariant = typename detail::variant_of_tuple<Tuple>::type;
template<class Tuple>
struct poly_tuple_iterator
{
using tuple_type = Tuple;
using value_type = ToVariant<std::remove_reference_t<tuple_type>>;
using difference_type = std::ptrdiff_t;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::random_access_iterator_tag;
struct concept {
virtual ~concept() = default;
virtual const std::type_info& type() const = 0;
virtual const void* address() const = 0;
virtual bool equal(const void* p) const = 0;
virtual std::unique_ptr<concept> clone() const = 0;
virtual std::unique_ptr<concept> next() const = 0;
virtual std::unique_ptr<concept> prev() const = 0;
virtual value_type deref() const = 0;
};
template<size_t I>
struct model : concept {
using my_type = tuple_iterator<tuple_type, I>;
model(my_type iter) : _iter(iter) {}
const std::type_info& type() const override { return typeid(_iter); }
const void* address() const override { return std::addressof(_iter); }
std::unique_ptr<concept> clone() const override { return std::make_unique<model<I>>(_iter); };
std::unique_ptr<concept> next() const override {
auto next_iter = ++_iter;
return std::make_unique<model<next_iter.index()>>(next_iter);
};
std::unique_ptr<concept> prev() const override {
auto next_iter = --_iter;
return std::make_unique<model<next_iter.index()>>(next_iter);
};
value_type deref() const override { return { *_iter }; }
bool equal(const void* p) const override {
return _iter == *reinterpret_cast<const my_type*>(p);
}
my_type _iter;
};
template<size_t I>
poly_tuple_iterator(tuple_iterator<tuple_type, I> iter)
: _impl(std::make_unique<model<I>>(iter))
{}
poly_tuple_iterator(const poly_tuple_iterator& r) : _impl(r._impl->clone()) {};
poly_tuple_iterator(poly_tuple_iterator&& r) : _impl(std::move(r._impl)) {};
poly_tuple_iterator& operator=(const poly_tuple_iterator& r) {
_impl = r._impl->clone();
return *this;
}
poly_tuple_iterator& operator=(poly_tuple_iterator&& r) {
auto tmp = r._impl->clone();
std::swap(tmp, _impl);
return *this;
}
value_type operator*() const { return _impl->deref(); }
poly_tuple_iterator& operator++() { _impl = _impl->next(); return *this; }
poly_tuple_iterator operator++(int) { auto tmp = *this; _impl = _impl->next(); return tmp; }
poly_tuple_iterator& operator--() { _impl = _impl->prev(); return *this; }
poly_tuple_iterator operator--(int) { auto tmp = *this; _impl = _impl->prev(); return tmp; }
poly_tuple_iterator& operator+=(difference_type dist) {
while (dist > 0) {
++(*this);
--dist;
}
while(dist < 0) {
--(*this);
++dist;
}
return *this;
}
bool operator==(const poly_tuple_iterator& r) const {
return _impl->type() == r._impl->type()
and _impl->equal(r._impl->address());
}
bool operator!=(const poly_tuple_iterator& r) const {
return not (*this == r);
}
private:
std::unique_ptr<concept> _impl;
};
template<class Tuple, size_t I>
auto make_poly_tuple_iterator(tuple_iterator<Tuple, I> iter) {
return poly_tuple_iterator<Tuple>(iter);
}
struct print_it : boost::static_visitor<void>
{
template<class T>
void operator()(const T& t) const {
std::cout << "printing: " << t << std::endl;
}
template<class...Ts>
void operator()(const boost::variant<Ts...>& v) const {
boost::apply_visitor(*this, v);
}
};
// to differentiate string types for this demo
template<class tag>
struct tagged_string : std::string
{
using std::string::string;
};
struct tag1 {};
struct tag2 {};
struct tag3 {};
int main()
{
using namespace std;
auto x = make_tuple(tagged_string<tag1>("dont print me"),
1,
2.0,
tagged_string<tag2>("three"),
tagged_string<tag3>("or me"));
for_each(next(begin(x)), prev(end(x)), [](const auto& x) { cout << x << endl; });
auto first = std::next(make_poly_tuple_iterator(begin(x)));
auto last = std::prev(make_poly_tuple_iterator(end(x)));
std::for_each(first, last, print_it());
return 0;
}

Implementing Haskell's Maybe Monad in c++11

I am trying to implement the Maybe monad from Haskell using the lambda functions in C++11 and templates. Here's what I have so far
#include<functional>
#include<iostream>
using namespace std;
template<typename T1>
struct Maybe
{
T1 data;
bool valid;
};
template<typename T1, typename T2>
Maybe<T2> operator>>=(Maybe<T1> t, std::function < Maybe<T2> (T1)> &f)
{
Maybe<T2> return_value;
if(t.valid == false)
{
return_value.valid = false;
return return_value;
}
else
{
return f(t.data);
}
}
int main()
{
Maybe<int> x = {5, true};
Maybe<int> y = {29, false};
auto z = [](int a) -> Maybe<int>
{
Maybe<int> s;
s.data = a+1;
s.valid = true;
return s;
};
Maybe<int> p = (x >>= z);
Maybe<int> q = (y >>= z);
cout<<p.data<<' '<<p.valid<<endl;
cout<<q.data<<' '<<q.valid<<endl;
}
When it comes to the actual >>= call, I am getting a compiler error saying that no match found for >>= operator. Is my understanding of C++11's lambda functions failing me here?
The type of a lambda isn't a specialization of std::function. It's some unamed type. There is a conversion to std::function, but that means type deduction won't work for it. So, in this call:
Maybe<int> p = (x >>= z);
The type T2 can't be deduced:
Maybe<T2> operator>>=(Maybe<T1> t, std::function < Maybe<T2> (T1)> &f)
Store the lambda in a std::function variable from the start, and it should work:
std::function < Maybe<int> (int)> z = [](int a) -> Maybe<int> { ... };
However, it's probably easier to accept any kind of function object. That way you can still use auto for the lambda.
template<typename T1, typename F>
typename std::result_of<F(T1)>::type
operator>>=(Maybe<T1> t, F&& f) {
... std::forward<F>(f)(t.data);
}
The following works for me: I use decltype to infer the type returned by the lambda:
template<typename T1, typename Func>
auto operator>>=(Maybe<T1> t, Func f) -> decltype(f(t.data))
{
decltype(f(t.data)) return_value;
if(t.valid == false)
{
return_value.valid = false;
return return_value;
}
else
{
return f(t.data);
}
}
EDIT
For type safety :
template<typename T1>
struct Maybe
{
T1 data;
bool valid;
static const bool isMaybe = true;
};
template<typename T1, typename Func>
auto operator>>=(Maybe<T1> t, Func f) -> decltype(f(t.data))
{
typedef decltype(f(t.data)) RT;
static_assert(RT::isMaybe, "F doesn't return a maybe");
...
Here's my maybe "monad" that I use quite often in my C++ projects (disclaimer: see the comments below). It's insofar more like the Haskell Maybe than your implementation as it only holds an object in the just case (points mobj on it), not wasting space if it's nothing. This also allows it to use of C++11 move semantics, to avoid unnecessary copies. The return types of fmap (fmapped member function) and >>= are deduced with decltype.
template<typename DataT>
class maybe;
template<typename DataT>
maybe<DataT> just(const DataT &obj);
struct nothing_object{nothing_object(){}};
const nothing_object nothing;
//template class objects of which may or may not contain some given
// data object. Inspired by Haskell's Maybe monad.
template<typename DataT>
class maybe {
DataT *obj;
public:
class iterator {
DataT *mobj;
explicit iterator(DataT *init):mobj(init){}
public:
iterator():mobj(nullptr){}
iterator(const iterator &cp):mobj(cp.mobj){}
bool operator!=(const iterator &other)const{return mobj!=other.mobj;}
DataT &operator*() const{return *mobj;}
iterator &operator++(){ mobj=nullptr; return *this; }
friend class maybe;
};
class const_iterator {
const DataT *mobj;
explicit const_iterator(const DataT *init):mobj(init){}
public:
const_iterator():mobj(nullptr){}
const_iterator(const const_iterator &cp):mobj(cp.mobj){}
bool operator!=(const const_iterator &other)const{return mobj!=other.mobj;}
const DataT &operator*() const{return *mobj;}
const_iterator &operator++(){ mobj=nullptr; return *this; }
friend class maybe;
};
iterator begin(){return iterator(obj);}
iterator end(){return iterator();}
const_iterator begin()const{return const_iterator(obj);}
const_iterator end()const{return const_iterator();}
const_iterator c_begin()const{return const_iterator(obj);}
const_iterator c_end()const{return const_iterator();}
bool is_nothing()const{return obj==nullptr;}
void make_nothing(){delete obj; obj=nullptr;}
bool is_just()const{return obj!=nullptr;}
template<typename CpDataT>
void with_just_assign(CpDataT &mdftg)const{if(obj) mdftg=*obj;}
DataT &from_just(){return *obj;}
DataT &operator*(){return *obj;}
const DataT &from_just()const{return *obj;}
const DataT &operator*()const{return *obj;}
template<typename CmpDataT>
bool operator==(const maybe<CmpDataT> &cmp)const{
return is_just()==cmp.is_just() && (is_nothing() || *obj==*cmp.obj); }
template<typename CmpDataT>
bool operator!=(const maybe<CmpDataT> &cmp)const{
return is_just()!=cmp.is_just() || (is_just() && *obj!=*cmp.obj); }
bool operator==(const nothing_object &n)const{return obj==nullptr;}
bool operator!=(const nothing_object &n)const{return obj!=nullptr;}
template<typename MpFnT>
auto fmapped(MpFnT f) const -> maybe<decltype(f(*obj))> {
return obj? just(f(*obj)) : nothing; }
template<typename MonadicFn>
auto operator>>=(MonadicFn f) const -> decltype(f(*obj)) {
return obj? f(*obj) : nothing; }
template<typename ReplaceDT>
auto operator>>(const maybe<ReplaceDT> &r) const -> maybe<ReplaceDT> {
return obj? r : nothing; }
auto operator>>(const nothing_object &n) const -> maybe<DataT> {
return nothing; }
maybe(const nothing_object &n):obj(nullptr){}
template<typename CpDataT>
explicit maybe(const CpDataT &cobj):obj(new DataT(cobj)){}
template<typename CpDataT>
maybe &operator=(const CpDataT &cobj){delete obj; obj=new DataT(cobj); return *this;}
template<typename CpDataT>
maybe(const maybe<CpDataT> &cp):obj(cp.is_just()?new DataT(cp.from_just()):nullptr){}
template<typename CpDataT>
maybe &operator=(const maybe<CpDataT> &cp){
delete obj; obj = cp.is_just()? new DataT(cp.from_just()) : nullptr; return *this;}
maybe(maybe<DataT> &&mv):obj(mv.obj){mv.obj=nullptr;}
maybe &operator=(maybe<DataT> &&mv) {
delete obj; obj=mv.obj; mv.obj=nullptr; return *this; }
~maybe(){delete obj;}
};
template<typename DataT>
auto just(const DataT &obj) -> maybe<DataT> {return maybe<DataT>(obj);}
template<typename MpFnT, typename DataT> // represents Haskell's <$> infix
auto operator^(MpFnT f, const maybe<DataT> &m) -> decltype(m.fmapped(f)) {
return m.fmapped(f);
}
template<typename DataT>
auto joined(const maybe<maybe<DataT>> &m) -> maybe<DataT> {
return m.is_just()? m.from_just() : nothing;
}
template<typename DataT>
auto maybe_yes(const std::pair<DataT,bool>& mbcst) -> maybe<DataT> {
return mbcst.second ? just(mbcst.first) : nothing;
}
template<typename DataT>
auto maybe_not(const std::pair<DataT,bool>& mbcst) -> maybe<DataT> {
return !mbcst.second ? just(mbcst.first) : nothing;
}
The somewhat strange-seeming begin and end iterators allow it to be used in C++11 range-based for loops:
maybe<int> a = just(7), b = nothing;
for (auto&i: a) std::cout << i;
for (auto&i: b) std::cout << i;
outputs only once 7.
Noticed that std::function have an empty state, we can have the following implementation
template<typename T>
class Maybe{
private:
Maybe(T t){
get = [t](){ return t; };
}
Maybe(){}
std::function<T ()> get;
public:
typedef T content_type;
template<typename WhenJust, typename WhenNothing>
auto on(WhenJust &&whenJust, WhenNothing &&whenNothing)
-> decltype(whenNothing()){
if(get==nullptr) return whenNothing();
else return whenJust(get());
}
template<typename U>
friend Maybe<U> just(U u);
template<typename U>
friend Maybe<U> nothing();
};
template<typename T>
Maybe<T> just(T t){
return Maybe<T>(t);
}
template<typename T>
Maybe<T> nothing(){
return Maybe<T>();
}
template<typename T, typename BinderFunction>
auto operator >>(Maybe<T> m, BinderFunction bind)
-> Maybe<typename decltype(bind(*((T*)nullptr)))::content_type> {
return m.on([bind](T v){
return bind(v);
},[](){
return nothing<typename decltype(bind(*((T*)nullptr)))::content_type>();
});
}
In this implementation, all factory methods are free (friend) functions, the >> operator (not to be confused with >> in Haskell, this is the equivalent of >>= with same associative) is also free, and even not a friend function. Also notice the on member function, this is used to force any client intended to use a Maybe instance must be prepared for both cases (Just or Nothing).
Here is an example of usage:
int main()
{
auto n = just(10) >> [](int j){ std::cout<<j<<" >> "; return just(j+10.5); }
>> [](double d){ std::cout<<d<<" >> "; return nothing<char>(); }
>> [](char c){ std::cout<<c; return just(10); }
;
n.on(
[](int i) { std::cout<<i; },
[]() { std::cout<<"nothing!"; });
std::cout << std::endl;
return 0;
}
The output is
10 >> 20.5 >> nothing!
My 5 cts.
Sample usage:
Maybe<string> m1 ("longlonglong");
auto res1 = m1 | lengthy | length;
lengthy and length are "monadic lambdas", i.e.
auto length = [] (const string & s) -> Maybe<int>{ return Maybe<int> (s.length()); };
Complete code:
// g++ -std=c++1y answer.cpp
#include <iostream>
using namespace std;
// ..................................................
// begin LIBRARY
// ..................................................
template<typename T>
class Maybe {
//
// note: move semantics
// (boxed value is never duplicated)
//
private:
bool is_nothing = false;
public:
T value;
using boxed_type = T;
bool isNothing() const { return is_nothing; }
explicit Maybe () : is_nothing(true) { } // create nothing
//
// naked values
//
explicit Maybe (T && a) : value(std::move(a)), is_nothing(false) { }
explicit Maybe (T & a) : value(std::move(a)), is_nothing(false) { }
//
// boxed values
//
Maybe (Maybe & b) : value(std::move(b.value)), is_nothing(b.is_nothing) { b.is_nothing = true; }
Maybe (Maybe && b) : value(std::move(b.value)), is_nothing(b.is_nothing) { b.is_nothing = true; }
Maybe & operator = (Maybe & b) {
value = std::move(b.value);
(*this).is_nothing = b.is_nothing;
b.is_nothing = true;
return (*this);
}
}; // class
// ..................................................
template<typename IT, typename F>
auto operator | (Maybe<IT> mi, F f) // chaining (better with | to avoid parentheses)
{
// deduce the type of the monad being returned ...
IT aux;
using OutMonadType = decltype( f(aux) );
using OT = typename OutMonadType::boxed_type;
// just to declare a nothing to return
Maybe<OT> nothing;
if (mi.isNothing()) {
return nothing;
}
return f ( mi.value );
} // ()
// ..................................................
template<typename MO>
void showMonad (MO m) {
if ( m.isNothing() ) {
cout << " nothing " << endl;
} else {
cout << " something : ";
cout << m.value << endl;
}
}
// ..................................................
// end LIBRARY
// ..................................................
// ..................................................
int main () {
auto lengthy = [] (const string & s) -> Maybe<string> {
string copyS = s;
if (s.length()>8) {
return Maybe<string> (copyS);
}
return Maybe<string> (); // nothing
};
auto length = [] (const string & s) -> Maybe<int>{ return Maybe<int> (s.length()); };
Maybe<string> m1 ("longlonglong");
Maybe<string> m2 ("short");
auto res1 = m1 | lengthy | length;
auto res2 = m2 | lengthy | length;
showMonad (res1);
showMonad (res2);
} // ()
Literally copy & pasting from Haskell style "Maybe" type & *chaining* in C++11
This is probably what you really want to achieve
#include <iostream>
#include <map>
#include <deque>
#include <algorithm>
#include <type_traits>
typedef long long int int64;
namespace monad { namespace maybe {
struct Nothing {};
template < typename T >
struct Maybe {
template < typename U, typename Enable = void >
struct ValueType {
typedef U * const type;
};
template < typename U >
struct ValueType < U, typename std::enable_if < std::is_reference < U >::value >::type > {
typedef typename std::remove_reference < T >::type * const type;
};
typedef typename ValueType < T >::type value_type;
value_type m_v;
Maybe(Nothing const &) : m_v(0) {}
struct Just {
value_type m_v;
Just() = delete;
explicit Just(T &v) : m_v(&v) {
}
};
Maybe(Just const &just) : m_v(just.m_v) {
}
};
Nothing nothing() {
return Nothing();
}
template < typename T >
Maybe < T > just(T &v) {
return typename Maybe < T >::Just(v);
}
template < typename T >
Maybe < T const > just(T const &v) {
return typename Maybe < T const >::Just(v);
}
template < typename T, typename R, typename A >
Maybe < R > operator | (Maybe < T > const &t, R (*f)(A const &)) {
if (t.m_v)
return just < R >(f(*t.m_v));
else
return nothing();
}
template < typename T, typename R, typename A >
Maybe < R > operator | (Maybe < T > const &t, Maybe < R > (*f)(A const &)) {
if (t.m_v)
return f(*t.m_v);
else
return nothing();
}
template < typename T, typename R, typename A >
Maybe < R > operator | (Maybe < T > const &t, R (*f)(A &)) {
if (t.m_v)
return just < R >(f(*t.m_v));
else
return nothing();
}
template < typename T, typename R, typename A >
Maybe < R > operator | (Maybe < T > const &t, Maybe < R > (*f)(A &)) {
if (t.m_v)
return f(*t.m_v);
else
return nothing();
}
template < typename T, typename R, typename... A >
Maybe < R > operator | (Maybe < T const > const &t, R (T::*f)(A const &...) const) {
if (t.m_v)
return just < R >(((*t.m_v).*f)());
else
return nothing();
}
template < typename T, typename R, typename... A >
Maybe < R > operator | (Maybe < T const > const &t, Maybe < R > (T::*f)(A const &...) const) {
if (t.m_v)
return just < R >((t.m_v->*f)());
else
return nothing();
}
template < typename T, typename R, typename... A >
Maybe < R > operator | (Maybe < T const > const &t, R (T::*f)(A const &...)) {
if (t.m_v)
return just < R >(((*t.m_v).*f)());
else
return nothing();
}
template < typename T, typename R, typename... A >
Maybe < R > operator | (Maybe < T const > const &t, Maybe < R > (T::*f)(A const &...)) {
if (t.m_v)
return just < R >((t.m_v->*f)());
else
return nothing();
}
template < typename T, typename A >
void operator | (Maybe < T > const &t, void (*f)(A const &)) {
if (t.m_v)
f(*t.m_v);
}
}}
struct Account {
std::string const m_id;
enum Type { CHECKING, SAVINGS } m_type;
int64 m_balance;
int64 withdraw(int64 const amt) {
if (m_balance < amt)
m_balance -= amt;
return m_balance;
}
std::string const &getId() const {
return m_id;
}
};
std::ostream &operator << (std::ostream &os, Account const &acct) {
os << "{" << acct.m_id << ", "
<< (acct.m_type == Account::CHECKING ? "Checking" : "Savings")
<< ", " << acct.m_balance << "}";
}
struct Customer {
std::string const m_id;
std::deque < Account > const m_accounts;
};
typedef std::map < std::string, Customer > Customers;
using namespace monad::maybe;
Maybe < Customer const > getCustomer(Customers const &customers, std::string const &id) {
auto customer = customers.find(id);
if (customer == customers.end())
return nothing();
else
return just(customer->second);
};
Maybe < Account const > getAccountByType(Customer const &customer, Account::Type const type) {
auto const &accounts = customer.m_accounts;
auto account = std::find_if(accounts.begin(), accounts.end(), [type](Account const &account) -> bool { return account.m_type == type; });
if (account == accounts.end())
return nothing();
else
return just(*account);
}
Maybe < Account const > getCheckingAccount(Customer const &customer) {
return getAccountByType(customer, Account::CHECKING);
};
Maybe < Account const > getSavingsAccount(Customer const &customer) {
return getAccountByType(customer, Account::SAVINGS);
};
int64 const &getBalance(Account const &acct) {
return acct.m_balance;
}
template < typename T >
void print(T const &v) {
std::cout << v << std::endl;
}
int main(int const argc, char const * const argv[]) {
Customers customers = {
{ "12345", { "12345", { { "12345000", Account::CHECKING, 20000 }, { "12345001", Account::SAVINGS, 117000 } } } }
, { "12346", { "12346", { { "12346000", Account::SAVINGS, 1000000 } } } }
};
getCustomer(customers, "12346") | getCheckingAccount | getBalance | &print < int64 const >;
getCustomer(customers, "12345") | getCheckingAccount | getBalance | &print < int64 const >;
getCustomer(customers, "12345") | getSavingsAccount | &Account::getId | &print < std::string const >;
// getCustomer(customers, "12345") | getSavingsAccount | [](Account &acct){ return acct.withdraw(100); } | &print < std::string const >;
}

C++ Iterator Pipelining Designs

Suppose we want to apply a series of transformations, int f1(int), int f2(int), int f3(int), to a list of objects. A naive way would be
SourceContainer source;
TempContainer1 temp1;
transform(source.begin(), source.end(), back_inserter(temp1), f1);
TempContainer2 temp2;
transform(temp1.begin(), temp1.end(), back_inserter(temp2), f2);
TargetContainer target;
transform(temp2.begin(), temp2.end(), back_inserter(target), f3);
This first solution is not optimal because of the extra space requirement with temp1 and temp2. So, let's get smarter with this:
int f123(int n) { return f3(f2(f1(n))); }
...
SourceContainer source;
TargetContainer target;
transform(source.begin(), source.end(), back_inserter(target), f123);
This second solution is much better because not only the code is simpler but more importantly there is less space requirement without the intermediate calculations.
However, the composition f123 must be determined at compile time and thus is fixed at run time.
How would I try to do this efficiently if the composition is to be determined at run time? For example, if this code was in a RPC service and the actual composition--which can be any permutation of any subset of f1, f2, and f3--is based on arguments from the RPC call.
EDIT: Working version at http://ideone.com/5GxnW . The version below has the ideas but does not compile. It supports run time type checking, and run time function composition.
The idea is to define a generic (unary) function class, and a way to compose them with run time type checks. This is done with a combination of boost::any, boost::function and the type erasure idiom.
#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
template <typename T>
struct identity
{
T operator()(const T& x) { return x; }
};
struct any_function
{
template <typename Res, typename Arg>
any_function(boost::function<Res, Arg> f)
{
impl = make_impl(f);
}
boost::any operator()(const boost::any& x)
{
return impl->invoke(x);
}
static any_function compose(const any_function& f,
const any_function& g)
{
any_function ans;
ans.impl = compose_impl(f.impl, g.impl);
return ans;
}
template <typename T>
static any_function id()
{
using boost::function
return any_function(function<T(T)>(identity<T>()));
}
template <typename Res, typename Arg>
boost::function<Res(Arg)> to_function()
{
using boost::function;
return function<Res(Arg)>(to_function_helper(impl));
}
private:
any_function() {}
struct impl_type
{
virtual ~impl_type() {}
virtual boost::any invoke(const boost::any&) = 0;
};
boost::shared_ptr<impl_type> impl;
template <typename Res, typename Arg>
static impl_type* make_impl(boost::function<Res(Arg)> f)
{
using boost::function;
using boost::any;
using boost::any_cast;
class impl : public impl_type
{
function<Res(Arg)> f;
any invoke(const any& x)
{
const Arg& a = any_cast<Arg>(x);
return any(f(a));
}
public:
impl(function<Res(Arg)> f) : f(f) {}
};
return new impl(f);
}
impl_type* compose_impl(boost::shared_ptr<impl_type> f,
boost::shared_ptr<impl_type> g)
{
using boost::any;
using boost::shared_ptr;
class impl : public impl_type
{
shared_ptr<impl> f, g;
any invoke(const any& x)
{
return g->invoke(f->invoke(x));
}
public:
impl(const shared_ptr<impl>& f,
const shared_ptr<impl>& g)
: f(f), g(g)
{}
};
return new impl(f, g);
}
struct to_function_helper
{
template <typename Res, typename Arg>
Res operator()(const Arg& x)
{
using boost::any;
using boost::any_cast;
return any_cast<Res>(p->invoke(any(x)));
}
to_function_helper(const boost::shared_ptr<impl>& p) : p(p) {}
private:
boost::shared_ptr<impl> p;
};
};
Now, let's use standard algorithms and do this (this even works on empty sequences):
// First function passed is evaluated first. Feel free to change.
template <typename Arg, typename Res, typename I>
boost::function<Res(Arg)> pipeline(I begin, I end)
{
return std::accumulate(begin, end,
any_function::id<Arg>,
std::ptr_fun(any_function::compose)
).to_function<Res, Arg>();
}
and use the following to apply it
std::vector<any_function> f;
std::vector<double> v;
std::vector<int> result;
std::transform(v.begin(), v.end(),
result.begin(),
pipeline<double, int>(f.begin(), f.end())
);
You can even use boost::transform_iterator
typedef boost::transform_iterator<
boost::function<double, int>,
std::vector<double>::const_iterator
> iterator;
boost::function<double, int> f = pipeline<double, int>(f.begin(), f.end());
std::copy(iterator(v.begin(), f), iterator(v.end(), f), result.begin());
template<class T>
class compose {
typedef T (*f)(T);
f first_func;
f second_func;
public:
compose(f one,f two) :
first_func(one),
second_func(two)
{}
T operator()(T const &input) {
T temp = first_func(input);
return second_func(temp);
}
};
#ifdef TEST
int f(int x) { return 8 + x; }
int g(int x) { return 2 * x; }
int h(int x) { return x * x; }
#include <iostream>
int main(int argc, char **argv) {
compose<int> x(f, g);
compose<int> y(g, f);
std::cout << x(6) << std::endl;
std::cout << y(6) << std::endl;
typedef int (*func)(int);
func funcs[] = {f, g, h};
compose<int> z(funcs[atoi(argv[1])], funcs[atoi(argv[2])]);
std::cout << z(6);
return 0;
}
#endif
With C++0x, we should be able to use auto to eliminate having to specify the argument/return type. For the moment I've assumed they're the same, though in theory, you might like the ability to include conversions in the mix.
you should use a functor instead of function and pass needed transform functions into functor's constructor
something like
typedef int (*FunctionType)(int);
class Functor
{
FunctionType m_f1;
FunctionType m_f2;
FunctionType m_f3;
public:
Functor(FunctionType f1, FunctionType f2, FunctionType f3):
m_f1(f1), m_f2(f2), m_f3(f3)
{}
int operator()(int n)
{
return (*m_f1)((*m_f2)((*m_f3)(n)));
}
};
// ...
transform(source.begin(), source.end(), back_inserter(temp1), Functor(f1,f2,f3));
if you need variable number of functions then change Functor constructor signature to use vector of functions and fill that vector before calling transform.
Just define an iterator that does what you want:
template<typename T>
struct source
{
virtual source<T>& operator++(void) = 0;
virtual T operator*(void) = 0;
virtual bool atend() = 0;
};
struct source_exhausted
{
};
template<typename T>
bool operator==(const source<T>& comparand, const source_exhausted&)
{ return comparand.atend(); }
template<typename T>
bool operator!=(const source<T>& comparand, const source_exhausted&)
{ return !comparand.atend(); }
template<typename T>
bool operator==(const source_exhausted&, const source<T>& comparand)
{ return comparand.atend(); }
template<typename T>
bool operator!=(const source_exhausted&, const source<T>& comparand)
{ return !comparand.atend(); }
template<typename T, typename iterT, typename endT>
struct source_iterator : source<T>
{
iterT m_iter;
endT m_end;
source_iterator(iterT iter, endT end) : m_iter(iter), m_end(end) {}
virtual source<T>& operator++(void) { ++m_iter; return *this; }
virtual T operator*(void) { return *m_iter; }
virtual bool atend() { return m_iter == m_end; }
};
template<typename T, typename iterT, typename endT>
auto make_source_iterator(iterT iter, endT end) -> source_iterator<decltype(*iter), iterT, endT>
{
return source_iterator<decltype(*iter), iterT, endT>(iter, end);
}
template<typename TContainer>
auto make_source_iterator(TContainer& c) -> source_iterator<typename TContainer::value_type, decltype(c.begin()), decltype(c.end())>
{
return source_iterator<typename TContainer::value_type, decltype(c.begin()), decltype(c.end())>(c.begin(), c.end());
}
template<typename TIn, typename TOut, typename TXform>
struct source_transformer : source<TOut>
{
source<TIn>& m_src;
TXform const m_f;
source_transformer( source<TIn>& src, TXform f ) : m_f(f), m_src(src) {}
virtual source<TOut>& operator++(void) { ++m_src; return *this; }
virtual TOut operator*(void) { return m_f(*m_src); }
virtual bool atend() { return m_src.atend(); }
};
template<typename TIn, typename TOut, typename TXform>
auto make_source_transformer(source<TIn>& src, TXform f) -> source_transformer<TIn, decltype(f(*(TIn*)0)), TXform>
{
return source_transformer<TIn, decltype(f(*(TIn*)0)), TXform>(src, f);
}
typedef int (*f_t)(int);
int f1(int a) { return a + 1; }
int f2(int a) { return a * 2; }
int f3(int a) { return a * a; }
int main()
{
std::vector<f_t> ff = {f1, f2, f3};
std::vector<int> source = {1, 2, 3, 4}, target;
std::transform(source.begin(), source.end(), std::back_inserter(target)
, [&](int a) { for (f_t &f : ff) a = f(a); return a; });
// print target
std::copy(target.begin(), target.end(), std::ostream_iterator<int,char>(std::cout,"\n"));
system("pause");
return 0;
}

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