boost.proto + unwrap expression from domain-specific expression wrapper - c++

Background question: boost.proto + modify expression tree in place
Hi, consider the following transform to extract the value_type from a vector_expr (see previous questions)
template <class T> struct value_type_trait;
template <std::size_t D, class T>
struct value_type_trait<vector<D, T> >
{
typedef typename vector<D, T>::value_type type;
};
struct deduce_value_type
: proto::or_<
proto::when <vector_terminal, value_type_trait<proto::_value>() >
, proto::when <scalar_terminal, proto::_value>
, proto::otherwise <
proto::_default<deduce_value_type>()
>
>
{};
The above code can be used to provide 'maximal' value_type to the expression tree, which is obtained applying the usual C++ promotion rules and Boost.TypeOf magic. The above is used as follows
template <class Expr>
struct vector_expr : proto::extends <Expr, vector_expr <Expr>, vector_domain>
{
typedef proto::extends <Expr, vector_expr <Expr>, vector_domain> base_type;
// OK! now my expression has a 'value_type'
typedef typename boost::result_of<deduce_value_type(Expr)>::type value_type;
vector_expr (Expr const &e) : base_type (e) {}
};
But now, the following code (check previous question: boost.proto + modify expression tree in place and the code in the accepted answer) is broken (with the usual humongous template instantiation error backtrace, for my pleasure)
int main ()
{
double data[] = {1, 2, 3};
vector<3, double> a(data, data+3), b(data,data+3), c(data,data+3);
auto iter = vector_begin_algo()(a + b);
return 0;
}
The reason is simple. The type of typename boost::result_of<vector_begin_algo(a+b)>::type is:
vector_expr<
basic_expr<
tag::plus
, list2< expr<tag::terminal, term<vector_iterator<double*> >, 0l>
, expr<tag::terminal, term<vector_iterator<double*> >, 0l>
>
,
2l>
>
So, the external vector_expr<...> triggers the evaluation of the nested value_type, but the deduce_value_type algorithm doesn't know how to extract the nested value_type from vector_iterator<double*>. One solution is to define a new traits and modify deduce_value_type as follows
// A further trait
template <class Iter>
struct value_type_trait<vector_iterator<Iter> >
{
typedef typename std::iterator_traits<Iter>::value_type type;
};
// Algorithm to deduce the value type of an expression.
struct deduce_value_type
: proto::or_<
proto::when <vector_terminal, value_type_trait<proto::_value>() >
, proto::when <scalar_terminal, proto::_value>
, proto::when <proto::terminal<vector_iterator<proto::_> > , value_type_trait<proto::_value>()> // <- need this now
, proto::otherwise <
proto::_default<deduce_value_type>()
>
>
{};
There are several problems with this approach, but the most important is: for each typedef or static constant that i find convenient defining in the vector_expr struct, I will need to perform all the above only to have the expression compile, even if an iterator-expression IS-NOT vector-expression and it makes no sense to enlarge the interface of vector_expr to accommodate transformed trees.
The question is: there is a way to transform the vector_expr tree, converting vector nodes into iterator nodes, while at the same time removing the vector-ness from the tree itself so that i do not incur in the above problems?
Thanks in advance, best regards!
UPDATE
Sorry, i changed the last part of the question now that my mind is more clear about what (i think) should be achieved. In the meantime, i tried to solve the thing by myself with a partial success (?), but I feel that there should be a better way (so I still need help!).
It seems to me that the problems come from having all the tree nodes wrapped in the vector_expr thing, that has the side-effect of putting requirement on the terminals (mainly the static stuff for successfully compiling). OTOH, once a valid vector_exp has been constructed (namely: obeying the vector_grammar), then i can transform it to a valid iterator_tree without further checks.
I tried to create a transform that changes back all vector_expr nodes in a tree into 'proto::expr'. The code is as follows:
template <class Expr, long Arity = Expr::proto_arity_c>
struct deep_copy_unwrap_impl;
template <class Expr>
struct deep_copy_unwrap_impl <Expr,0>
{
typedef typename proto::tag_of <Expr>::type Tag;
typedef typename proto::result_of::value<Expr>::type A0;
typedef typename proto::result_of::make_expr<Tag, proto::default_domain, A0>::type result_type;
template<typename Expr2, typename S, typename D>
result_type operator()(Expr2 const &e, S const &, D const &) const
{
return proto::make_expr <Tag, proto::default_domain> (e.proto_base().child0);
}
};
template <class Expr>
struct deep_copy_unwrap_impl <Expr,1>
{
typedef typename proto::tag_of <Expr>::type Tag;
typedef typename proto::result_of::child_c<Expr, 0>::type A0;
typedef typename proto::result_of::make_expr<Tag, proto::default_domain, A0>::type result_type;
template<typename Expr2, typename S, typename D>
result_type operator()(Expr2 const &e, S const &, D const &) const
{
return proto::make_expr <Tag, proto::default_domain> (e.proto_base().child0);
}
};
template <class Expr>
struct deep_copy_unwrap_impl <Expr,2>
{
typedef typename proto::tag_of <Expr>::type Tag;
typedef typename proto::result_of::child_c<Expr, 0>::type A0;
typedef typename proto::result_of::child_c<Expr, 1>::type A1;
typedef typename proto::result_of::make_expr<Tag, proto::default_domain, A0, A1>::type result_type;
template<typename Expr2, typename S, typename D>
result_type operator()(Expr2 const &e, S const &, D const &) const
{
return proto::make_expr <Tag, proto::default_domain> (e.proto_base().child0, e.proto_base().child1);
}
};
struct unwrap : proto::callable
{
template <class Sig> struct result;
template <class This, class Expr>
struct result <This(Expr)>
{
typedef typename
deep_copy_unwrap_impl <Expr>
::result_type type;
};
template <class This, class Expr>
struct result <This(Expr&)>
: result<This(Expr)> {};
template <class This, class Expr>
struct result <This(Expr const&)>
: result<This(Expr)> {};
template <class Expr>
typename result <unwrap(Expr)>::type
operator () (Expr const &e) const
{
return deep_copy_unwrap_impl<Expr>()(e, 0, 0);
}
};
struct retarget
: proto::otherwise <
unwrap(proto::nary_expr<proto::_, proto::vararg<retarget> >)
>
{};
int main ()
{
int data[] = {1, 2, 3};
vector<3, int> a(data, data+3), b(data,data+3), c(data,data+3);
auto x=a+b+c; // <- x is an expression tree made up of vector_expr<...> nodes
auto y=retarget()(x); // <- y is an expression tree made up of proto::expr<...> nodes
return 0;
}

The problem you're running into is that Proto's pass_through transform creates new expressions that are in the same domain as the original. This happens in your vector_begin_algo algorithm, in the otherwise clause. You don't want this, but it's what pass_through gives you. You have two strategies: don't use pass_through, or trick pass_through into building an expression in the default domain.
If you're using the latest version of Proto (1.51), you can use make_expr and an unpacking expression instead of pass_through:
// Turn all vector terminals into vector iterator terminals
struct vector_begin_algo
: proto::or_<
proto::when<
proto::terminal<std::vector<_, _> >
, proto::_make_terminal(
vector_iterator<begin(proto::_value)>(begin(proto::_value))
)
>
, proto::when<
proto::terminal<_>
, proto::_make_terminal(proto::_byval(proto::_value))
>
, proto::otherwise<
proto::lazy<
proto::functional::make_expr<proto::tag_of<_>()>(
vector_begin_algo(proto::pack(_))...
)
>
>
>
{};
proto::lazy is needed here because you first need to build the make_expr function object before you can invoke it. It's not a thing of beauty, but it works.
If you are using an older version of Proto, you can get the same effect by tricking pass_through by first removing the domain-specific wrapper from your expression. First, I write a callable to strip the domain-specific wrapper:
struct get_base_expr
: proto::callable
{
template<typename Expr>
struct result;
template<typename This, typename Expr>
struct result<This(Expr)>
{
typedef
typename boost::remove_reference<Expr>::type::proto_base_expr
type;
};
template<typename Expr>
typename Expr::proto_base_expr operator()(Expr const &expr) const
{
return expr.proto_base();
}
};
Then, the vector_begin_algo would be changed as follows:
// Turn all vector terminals into vector iterator terminals
struct vector_begin_algo
: proto::or_<
proto::when<
proto::terminal<std::vector<_, _> >
, proto::_make_terminal(
vector_iterator<begin(proto::_value)>(begin(proto::_value))
)
>
, proto::when<
proto::terminal<_>
, proto::_make_terminal(proto::_byval(proto::_value))
>
, proto::otherwise<
proto::_byval(proto::pass_through<
proto::nary_expr<_, proto::vararg<vector_begin_algo> >
>(get_base_expr(_)))
>
>
{};
This is also not a work of art, but it gets the job done. Don't forget the proto::_byval to work around the const weirdness in the pass_through transform (which is fixed is boost trunk and will be in 1.52, btw).
I can think of one final solution that takes advantage of the fact that Proto expressions are Fusion sequences of their children. You create a Fusion transform_view that wraps the expression and transforms each child with vector_begin_algo. That gets passed to proto::functional::unpack_expr, much like in the first example with make_expr. You'd need proto::lazy there also, for the same reason.
Thanks for pointing out this limitation on Proto's built-in pass_through transform. It'd be good to have a nicer way to do this.

Related

Cannot deduce return type of lambda with std::map

This is a strange case.
The following code produces error when using User defined types but not when using primitives!
It produces errors with std::map (also QMap) but not if replaced with std::pair (also QPair)!
Why?
I'm using MSVC 2013.
class Class {};
typedef double Type; // This works fine
//typedef Class Type; // This produces error
template<typename T, typename ValueFunctor>
std::map<int, typename std::result_of<ValueFunctor(T)>::type >
testFun(ValueFunctor valueFunctor)
{
std::map<int, typename std::result_of<ValueFunctor(T)>::type > map;
return map;
}
void test()
{
std::map<int,Type> output = testFun<Type>(
// The error can be removed by explicitly specifying return type
[](const Type &pair)/*->T2*/{
return pair;
}
);
}
What's happening here is that in MSVC 2013 and earlier, the std::result_of template is returning a const Class instead of just Class. That causes the value type of map to be non-copyable.
You can see exactly the same problem by changing typedef double Type to typedef const double Type.
If you still have to use a non C++11 compliant library, you can specify the return type of the lambda to be Type but that would involve a copy.
Alternatively, remove the constness but changing:
typename std::result_of<ValueFunctor(T)>::type
to
typename std::remove_const<typename std::result_of<ValueFunctor(T)>::type >::type
template<typename T, typename ValueFunctor>
std::map<int, typename std::remove_const<typename std::result_of<ValueFunctor(T)>::type >::type>
testFun(ValueFunctor valueFunctor)
{
std::map<int, typename std::remove_const<typename std::result_of<ValueFunctor(T)>::type>::type > map;
return map;
}

How can I use C++11 variadic templates to define a vector-of-tuples backed by a tuple-of-vectors?

Suppose I have a bunch of vectors:
vector<int> v1;
vector<double> v2;
vector<int> v3;
all of the same length. Now, for every index i, I would like to be able to treat (v1[i], v2[i], v3[i]) as a tuple, and maybe pass it around. In fact, I want to have a a vector-of-tuples rather than a tuple-of-vectors, using which I can do the above. (In C terms, I might say an array-of-structs rather than a struct-of-arrays). I do not want to effect any data reordering (think: really long vectors), i.e. the new vector is backed by the individual vectors I pass in. Let's .
Now, I want the class I write (call it ToVBackedVoT for lack of a better name) to support any arbitrary choice of vectors to back it (not just 3, not int, double and int, not every just scalars). I want the vector-of-tuples to be mutable, and for no copies to be made on construction/assignments.
If I understand correctly, variadic templates and the new std::tuple type in C++11 are the means for doing this (assuming I don't want untyped void* arrays and such). However, I only barely know them and have never worked with them. Can you help me sketch out how such a class will look like? Or how, given
template <typename ... Ts>
I can express something like "the list of template arguments being the replacement of each typename in the original template arguments with a vector of elements of this type"?
Note: I think I might also want to later be able to adjoin additional vectors to the backing vectors, making an instance of ToVBackedVoT<int, double, int> into, say, an instance of ToVBackedVoT<int, double, int, unsigned int>. So, bear that in mind when answering. This is not critically important though.
One idea is to keep the storage in the "struct of array" style in form of vectors for good performance if only a subset of the fields are used for a particular task. Then, for each kind of task requiring a different set of fields, you can write a lightweight wrapper around some of those vectors, giving you a nice random access iterator interface similar to what std::vector supports.
Concerning the syntax of variadic templates, this is how a wrapper class (without any iterators yet) could look like:
template<class ...Ts> // Element types
class WrapMultiVector
{
// references to vectors in a TUPLE
std::tuple<std::vector<Ts>&...> m_vectors;
public:
// references to vectors in multiple arguments
WrapMultiVector(std::vector<Ts> & ...vectors)
: m_vectors(vectors...) // construct tuple from multiple args.
{}
};
To construct such a templated class, it's often preferred to have a template type deducting helper function available (similar to those make_{pair|tuple|...} functions in std):
template<class ...Ts> // Element types
WrapMultiVector<Ts...> makeWrapper(std::vector<Ts> & ...vectors) {
return WrapMultiVector<Ts...>(vectors...);
}
You already see different types of "unpacking" the type list.
Adding iterators suitable to your application (you requested in particular random access iterators) is not so easy. A start could be forward only iterators, which you might extend to random access iterators.
The following iterator class is capable of being constructed using a tuple of element iterators, being incremented and being dereferenced to obtain a tuple of element references (important for read-write access).
class iterator {
std::tuple<typename std::vector<Ts>::iterator...> m_elemIterators;
public:
iterator(std::tuple<typename std::vector<Ts>::iterator...> elemIterators)
: m_elemIterators(elemIterators)
{}
bool operator==(const iterator &o) const {
return std::get<0>(m_elemIterators) == std::get<0>(o.m_elemIterators);
}
bool operator!=(const iterator &o) const {
return std::get<0>(m_elemIterators) != std::get<0>(o.m_elemIterators);
}
iterator& operator ++() {
tupleIncrement(m_elemIterators);
return *this;
}
iterator operator ++(int) {
iterator old = *this;
tupleIncrement(m_elemIterators);
return old;
}
std::tuple<Ts&...> operator*() {
return getElements(IndexList());
}
private:
template<size_t ...Is>
std::tuple<Ts&...> getElements(index_list<Is...>) {
return std::tie(*std::get<Is>(m_elemIterators)...);
}
};
For demonstration purposes, two different patterns are in this code which "iterate" over a tuple in order to apply some operation or construct a new tuple with some epxression to be called per element. I used both in order to demonstrate alternatives; you can also use the second method only.
tupleIncrement: You can use a helper function which uses meta programming to index a single entry and advance the index by one, then calling a recursive function, until the index is at the end of the tuple (then there is a special case implementation which is triggered using SFINAE). The function is defined outside of the class and not above; here is its code:
template<std::size_t I = 0, typename ...Ts>
inline typename std::enable_if<I == sizeof...(Ts), void>::type
tupleIncrement(std::tuple<Ts...> &tup)
{ }
template<std::size_t I = 0, typename ...Ts>
inline typename std::enable_if<I < sizeof...(Ts), void>::type
tupleIncrement(std::tuple<Ts...> &tup)
{
++std::get<I>(tup);
tupleIncrement<I + 1, Ts...>(tup);
}
This method can't be used to assign a tuple of references in the case of operator* because such a tuple has to be initialized with references immediately, which is not possible with this method. So we need something else for operator*:
getElements: This version uses an index list (https://stackoverflow.com/a/15036110/592323) which gets expanded too and then you can use std::get with the index list to expand full expressions. The IndexList when calling the function instantiates an appropriate index list which is only required for template type deduction in order to get those Is.... The type can be defined in the wrapper class:
// list of indices
typedef decltype(index_range<0, sizeof...(Ts)>()) IndexList;
More complete code with a little example can be found here: http://ideone.com/O3CPTq
Open problems are:
If the vectors have different sizes, the code fails. Better would be to check all "end" iterators for equality; if one iterator is "at end", we're also "at end"; but this would require some logic more than operator== and operator!= unless it's ok to "fake" it in; meaning that operator!= could return false as soon as any operator is unequal.
The solution is not const-correct, e.g. there is no const_iterator.
Appending, inserting etc. is not possible. The wrapper class could add some insert or and / or push_back function in order to make it work similar to std::vector. If your goal is that it's syntactically compatible to a vector of tuples, reimplement all those relevant functions from std::vector.
Not enough tests ;)
An alternative to all the variadic template juggling is to use the boost::zip_iterator for this purpose. For example (untested):
std::vector<int> ia;
std::vector<double> d;
std::vector<int> ib;
std::for_each(
boost::make_zip_iterator(
boost::make_tuple(ia.begin(), d.begin(), ib.begin())
),
boost::make_zip_iterator(
boost::make_tuple(ia.end(), d.end(), ib.end())
),
handle_each()
);
Where your handler, looks like:
struct handle_each :
public std::unary_function<const boost::tuple<const int&, const double&, const int&>&, void>
{
void operator()(const boost::tuple<const int&, const double&, const int&>& t) const
{
// Now you have a tuple of the three values across the vector...
}
};
As you can see, it's pretty trivial to expand this to support an arbitrary set of vectors..
From asker's clarification on how this would be used (code that takes a tuple), I'm going to propose this instead.
//give the i'th element of each vector
template<typename... Ts>
inline tuple<Ts&...> ith(size_t i, vector<Ts>&... vs){
return std::tie(vs[i]...);
}
There's a proposal to allow parameter packs to be saved as members of classes (N3728). Using that, here's some untested and untestable code.
template<typename... Types>
class View{
private:
vector<Types>&... inner;
public:
typedef tuple<Types&...> reference;
View(vector<Types>&... t): inner(t...) {}
//return smallest size
size_t size() const{
//not sure if ... works with initializer lists
return min({inner.size()...});
}
reference operator[](size_t i){
return std::tie(inner[i]...);
}
};
And iteration:
public:
iterator begin(){
return iterator(inner.begin()...);
}
iterator end(){
return iterator(inner.end()...);
}
//for .begin() and .end(), so that ranged-based for can be used
class iterator{
vector<Types>::iterator... ps;
iterator(vector<Types>::iterator... its):ps(its){}
friend View;
public:
//pre:
iterator operator++(){
//not sure if this is allowed.
++ps...;
//use this if not:
// template<typename...Types> void dummy(Types... args){} //global
// dummy(++ps...);
return *this;
}
iterator& operator--();
//post:
iterator operator++(int);
iterator operator--(int);
//dereference:
reference operator*()const{
return std::tie(*ps...);
}
//random access:
iterator operator+(size_t i) const;
iterator operator-(size_t i) const;
//need to be able to check end
bool operator==(iterator other) const{
return std::make_tuple(ps...) == std::make_tuple(other.ps...);
}
bool operator!=(iterator other) const{
return std::make_tuple(ps...) != std::make_tuple(other.ps...);
}
};
You may use something like:
#if 1 // Not available in C++11, so write our own
// class used to be able to use std::get<Is>(tuple)...
template<int... Is>
struct index_sequence { };
// generator of index_sequence<Is>
template<int N, int... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> { };
template<int... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> { };
#endif
// The 'converting' class
// Note that it doesn't check that vector size are equal...
template<typename ...Ts>
class ToVBackedVoT
{
public:
explicit ToVBackedVoT(std::vector<Ts>&... vectors) : data(vectors...) {}
std::tuple<const Ts&...> operator [] (unsigned int index) const
{
return at(index, make_index_sequence<sizeof...(Ts)>());
}
std::tuple<Ts&...> operator [] (unsigned int index)
{
return at(index, make_index_sequence<sizeof...(Ts)>());
}
private:
template <int... Is>
std::tuple<const Ts&...> at(unsigned int index, index_sequence<Is...>) const
{
return std::tie(std::get<Is>(data)[index]...);
}
template <int... Is>
std::tuple<Ts&...> at(unsigned int index, index_sequence<Is...>)
{
return std::tie(std::get<Is>(data)[index]...);
}
private:
std::tuple<std::vector<Ts>&...> data;
};
And to iterate, create an 'IndexIterator' like the one in https://stackoverflow.com/a/20272955/2684539
To adjoin additional vectors, you have to create an other ToVBackedVoT as std::tuple_cat does for std::tuple
Conversion to a std::tuple of vectors (vector::iterators):
#include <iostream>
#include <vector>
// identity
// ========
struct identity
{
template <typename T>
struct apply {
typedef T type;
};
};
// concat_operation
// ================
template <typename Operator, typename ...> struct concat_operation;
template <
typename Operator,
typename ...Types,
typename T>
struct concat_operation<Operator, std::tuple<Types...>, T>
{
private:
typedef typename Operator::template apply<T>::type concat_type;
public:
typedef std::tuple<Types..., concat_type> type;
};
template <
typename Operator,
typename ...Types,
typename T,
typename ...U>
struct concat_operation<Operator, std::tuple<Types...>, T, U...>
{
private:
typedef typename Operator::template apply<T>::type concat_type;
public:
typedef typename concat_operation<
Operator,
std::tuple<Types..., concat_type>,
U...>
::type type;
};
template <
typename Operator,
typename T,
typename ...U>
struct concat_operation<Operator, T, U...>
{
private:
typedef typename Operator::template apply<T>::type concat_type;
public:
typedef typename concat_operation<
Operator,
std::tuple<concat_type>,
U...>
::type type;
};
// ToVectors (ToVBackedVoT)
// =========
template <typename ...T>
struct ToVectors
{
private:
struct to_vector {
template <typename V>
struct apply {
typedef typename std::vector<V> type;
};
};
public:
typedef typename concat_operation<to_vector, T...>::type type;
};
// ToIterators
// ===========
template <typename ...T>
struct ToIterators;
template <typename ...T>
struct ToIterators<std::tuple<T...>>
{
private:
struct to_iterator {
template <typename V>
struct apply {
typedef typename V::iterator type;
};
};
public:
typedef typename concat_operation<to_iterator, T...>::type type;
};
int main() {
typedef ToVectors<int, double, float>::type Vectors;
typedef ToVectors<Vectors, int, char, bool>::type MoreVectors;
typedef ToIterators<Vectors>::type Iterators;
// LOG_TYPE(Vectors);
// std::tuple<
// std::vector<int, std::allocator<int> >,
// std::vector<double, std::allocator<double> >,
// std::vector<float, std::allocator<float> > >
// LOG_TYPE(Iterators);
// std::tuple<
// __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >,
// __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >,
// __gnu_cxx::__normal_iterator<float*, std::vector<float, std::allocator<float> > > >
}
As an alternative similar to boost::zip_iterator I wrote a zip function with a very simple interface:
vector<int> v1;
vector<double> v2;
vector<int> v3;
auto vec_of_tuples = zip(v1, v2, v3);
For example, iterate over these tuples:
for (auto tuple : zip(v1, v2, v3)) {
int x1; double x2; int x3;
std::tie(x1, x2, x3) = tuple;
//...
}
Here, zip() takes any number of ranges of any type. It returns an adaptor which can be seen as a lazily evaluated range over a tuple of elements originating from the wrapped ranges.
The adaptor is part of my Haskell-style functional library "fn" and implemented using variadic templates.
Currently it doesn't support modification of the original ranges' values via the adaptor because of the design of the library (it's intended to be used with non-mutable ranges like in functional programming).
A brief explanation on how this is done is: zip(...) returns an adaptor object which implements begin() and end(), returning an iterator object. The iterator holds a tuple of iterators to the wrapped ranges. Incrementing the iterator increments all wrapped iterators (which is implemented using an index list and unpacking an incrementing expression into a series of expressions: ++std::get<I>(iterators)...). Dereferencing the iterator will decrement all wrapped iterators and pass it to std::make_tuple (which is also implemented as unpacking the expression *std::get<I>(iterators)...).
P.S. Its implementation is based on a lot of ideas coming from answers to this question.

Adding element to back of STL container

I'm looking for a general way of adding an element to the back of an STL container. I would like the code to support as many types of STL container as possible. The following piece of code demonstrates my problem:
#include <vector>
#include <string>
using namespace std;
template<typename T>
class S {
T built;
typename T::iterator built_it;
public:
S() : built{}, built_it{built.end()} {}
void add_to(typename T::value_type e) {
built.emplace(built_it, e);
++built_it;
}
const T& get() {
return built;
}
};
int main()
{
S<std::vector<int>> e;
S<std::string> f;
e.add_to(3); // works
f.add_to('c'); // doesn't
}
The problem here is subtle. This code works great for vectors, because std::vector implements the emplace function. But std::string does not! Is there a more general way to perform the same operation?
The most generic way (not necessarily the most efficient way) is:
c.insert( c.end(), value );
where, of course, value needs to be suitable for the container c (you may use decltype(c)::value_type). In case of an associative container, e.g. map, it is a std::pair.
This works for all standard containers except for std::forward_list. For some containers the element is then added at the end, for some the c.end() is just a hint that might be ignored.
As a follow up to the comments, here's the advanced stuff ;)
When you want to insert a known number of elements into a given container c (of type C) and you want to be at least somewhat efficient, you should detect wether the container type supports reserve() and call it before inserting elements.
The following method detects reserve() correctly (the link explains how):
template< typename C, typename = void >
struct has_reserve
: std::false_type
{};
template< typename C >
struct has_reserve< C, std::enable_if_t<
std::is_same<
decltype( std::declval<C>().reserve( std::declval<typename C::size_type>() ) ),
void
>::value
> >
: std::true_type
{};
Now you can use it with std::enable_if_t to optionally reserve space. An example could look like this:
template< typename C >
std::enable_if_t< !has_reserve< C >::value >
optional_reserve( C&, std::size_t ) {}
template< typename C >
std::enable_if_t< has_reserve< C >::value >
optional_reserve( C& c, std::size_t n )
{
c.reserve( c.size() + n );
}
template< typename C, typename T, std::size_t N >
void add_array( C& c, const std::array< T, N >& a )
{
optional_reserve( c, N );
for( const auto& e : a ) {
c.insert( c.end(), typename C::value_type( e ) ); // see remark below
}
}
add_array can now be called with all standard containers (except std::forward_list) and it will call reserve() for std::vector and the unordered associative containers.
As the above does not need explicit specialization or overloading for specific container types, it also works for non-standard containers as long as their interfaces are designed reasonably similar to the standard containers' interfaces. (In fact I had several such "home-made" containers in the past and the above Just-Works™)
A remark about the conversion in the above code: The reason for converting the Ts to C::value_type is just to show that this would be the correct place if it is needed. In the above example it might look superfluous, but in my real-world code I call a special conversion traits class to convert the es (which are encoded strings) into the correct value type for any container.
Most often, people use traits.
Many boost libraries have solved this same problem, so you might be able to reuse existing traits.
A simple demonstration: Live on Coliru
#include <vector>
#include <set>
#include <string>
namespace traits
{
template <typename Container, typename Enable = void>
struct add_at_end;
template <typename... TAs>
struct add_at_end<std::vector<TAs...> >
{
using Container = std::vector<TAs...>;
template <typename... CtorArgs>
static void apply(Container& container, CtorArgs&&... args) {
container.emplace_back(std::forward<CtorArgs>(args)...);
}
};
template <typename... TAs>
struct add_at_end<std::set<TAs...> >
{
using Container = std::set<TAs...>;
template <typename... CtorArgs>
static void apply(Container& container, CtorArgs&&... args) {
container.insert(container.end(), { std::forward<CtorArgs>(args)...});
}
};
template <typename... TAs>
struct add_at_end<std::basic_string<TAs...> >
{
using Container = std::basic_string<TAs...>;
template <typename... CtorArgs>
static void apply(Container& container, CtorArgs&&... args) {
container.insert(container.end(), { std::forward<CtorArgs>(args)...});
}
};
}
template <typename Container, typename... CtorArgs>
void add_to(Container& container, CtorArgs&&... args) {
traits::add_at_end<Container>::apply(container, std::forward<CtorArgs>(args)...);
}
int main()
{
using X = std::pair<int, std::string>;
std::vector<X> v;
std::set<X> s;
std::wstring wstr;
std::string str;
add_to(v, 12, "hello");
add_to(s, 42, "world");
add_to(wstr, L'!');
add_to(str, '?');
}
Basically, what you do, is have a free-standing utility function add_to that uses a trait class traits::add_at_end that can be specialized (in this case for any vector<...>, set<...>, or basic_string<...> template instances.
In practice, you would share the implementation for similar containers (e.g. deque and vector) by inheriting the common implementation.
push_back is supported by std::string, std::vector, and std::list. With this, your class template is simply:
template<typename T>
class S {
T built;
public:
S() : built{} {}
void add_to(typename T::value_type e) {
built.push_back(e);
}
const T& get() {
return built;
}
};

boost.proto + modify expression tree in place

Background question: boost.proto + detect invalid terminal before building the expression tree.
Hi, what i'm trying to achieve is
create a copy of an expression tree, where all vectors are substituted with
their begin iterators (in my case is a raw pointer)
increment the iterators in place
dereference iterators in the tree, but that part should be relatively easy.
So, for 1. I ended up with this code
///////////////////////////////////////////////////////////////////////////////
// A transform that converts all vectors nodes in a tree to iterator nodes
struct vector_begin : proto::transform <vector_begin>
{
template<typename Expr, typename Unused1, typename Unused2>
struct impl : boost::proto::transform_impl<Expr, Unused1, Unused2>
{
// must strip away the reference qualifier (&)
typedef typename proto::result_of::value<
typename boost::remove_reference<Expr>::type
>::type vector_type;
typedef typename proto::result_of::as_expr
<typename vector_type::const_iterator>::type result_type;
result_type operator ()(
typename impl::expr_param var
, typename impl::state_param
, typename impl::data_param) const
{
typename vector_type::const_iterator iter(proto::value(var).begin());
return proto::as_expr(iter); // store iterator by value
}
};
};
struct vector_grammar_begin
: proto::or_ <
proto::when <vector_terminal, vector_begin>
// scalars want to be stored by value (proto stores them by const &), if not the code does not compile...
, proto::when <scalar_terminal, boost::proto::_make_terminal(boost::proto::_byval(boost::proto::_value))>
// descend the tree converting vectors to begin() iterators
, proto::when <proto::nary_expr<_, proto::vararg<vector_grammar_begin> > >
>
{};
The above succeeds to create a tree where all vectors are replaced by pointers. So far, so good. Now, try to increment
iterators. I realized that is would be better to advance iterators, so with just one transform, i could get most of the
behavior of a random access iterator (dereference is the other missing piece). For 2., the required transform should be
///////////////////////////////////////////////////////////////////////////////
// A transform that advances all iterators in a tree
struct iter_advance : proto::transform <iter_advance>
{
template<typename Expr, typename Index, typename Dummy>
struct impl : boost::proto::transform_impl<Expr, Index, Dummy>
{
typedef void result_type;
result_type operator ()(
typename impl::expr_param var
, typename impl::state_param index // i'm using state to pass a data :(
, typename impl::data_param) const
{
proto::value(var)+=index; // No good... compile error here :(
}
};
};
// Ok, this is brittle, what if I decide the change vector<D,T>'s iterator type ?
struct iter_terminal
: proto::and_<
proto::terminal<_>
, proto::if_<boost::is_pointer<proto::_value>()>
>
{};
struct vector_grammar_advance
: proto::or_ <
proto::when <iter_terminal, iter_advance>
, proto::terminal<_>
, proto::when <proto::nary_expr<_, proto::vararg<vector_grammar_advance> > >
>
{};
Now, in the main function
template <class Expr>
void check_advance (Expr const &e)
{
proto::display_expr (e);
typedef typename boost::result_of<vector_grammar_begin(Expr)>::type iterator_type;
iterator_type iter = vector_grammar_begin()(e);
proto::display_expr (iter);
vector_grammar_advance ()(iter,1);
proto::display_expr (iter);
}
int main (int, char**)
{
vec<3, double> a(1), b(2), c(3);
check_advance(2*a+b/c);
return 0;
}
I get the following error message (filtered out the junk):
array.cpp:361:13: error: assignment of read-only location
'boost::proto::value<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const double*>, 0l> >((* & var))'
What bothers me is the '((* & var))' part... cannot understand what to do to fix this.
Thanks in advance, best regards
PS
Unrelated thing: after playing a little with transforms, the general pattern i'm using is:
Decide what to do to the tree
Write a primitive transform that performs the operation
Write a grammar that recognizes where the transform should be applied, use the previously defined transform
Do you think this is reasonable? I mean, it is a lot of code to perform just an elementary op to a single
kind of node. With contexts, it is possible to define several ops at once, discriminating on the node type.
It is possible to do this with transforms also ? What is the general pattern to be used?
Your intuition is correct; you should be able to mutate the tree in-place. There seems to be some const weirdness with Proto's pass_through transform that I need to investigate, so the solution is a little non-obvious. First, I define some callables that I will use in the Proto algorithms. I prefer callables to primitive transforms because they are simpler to grok, more reusable, and result in easier-to-read Proto algorithms.
struct begin
: proto::callable
{
template<typename Sig>
struct result;
template<typename This, typename Rng>
struct result<This(Rng)>
: boost::range_iterator<Rng>
{};
template<typename This, typename Rng>
struct result<This(Rng &)>
: boost::range_iterator<Rng>
{};
template<typename Rng>
typename boost::range_iterator<Rng>::type
operator()(Rng &rng) const
{
return boost::begin(rng);
}
template<typename Rng>
typename boost::range_iterator<Rng const>::type
operator()(Rng const &rng) const
{
return boost::begin(rng);
}
};
struct advance
: proto::callable
{
typedef void result_type;
template<typename Iter>
void operator()(Iter &it, unsigned d) const
{
it += d;
}
};
Now, I solve your brittleness problem with a simple iterator adaptor:
template<typename Iter>
struct vector_iterator
: boost::iterator_adaptor<vector_iterator<Iter>, Iter>
{
vector_iterator()
: boost::iterator_adaptor<vector_iterator<Iter>, Iter>()
{}
explicit vector_iterator(Iter iter)
: boost::iterator_adaptor<vector_iterator<Iter>, Iter>(iter)
{}
friend std::ostream &operator<<(std::ostream &sout, vector_iterator it)
{
return sout << "vector_iterator(value: " << *it << " )";
}
};
Here's the algorithm to turn a tree containing vectors into a tree containing vector iterators.
// Turn all vector terminals into vector iterator terminals
struct vector_begin_algo
: proto::or_<
proto::when<
proto::terminal<std::vector<_, _> >
, proto::_make_terminal(
vector_iterator<begin(proto::_value)>(begin(proto::_value))
)
>
, proto::when<
proto::terminal<_>
, proto::_make_terminal(proto::_byval(proto::_value))
>
, proto::otherwise<
proto::_byval(proto::nary_expr<_, proto::vararg<vector_begin_algo> >)
>
>
{};
The last proto::_byval shouldn't be needed. The pass_through transform used by proto::nary_expr shouldn't be creating const temporary nodes. Sorry about that.
And here is the algorithm to advance all the iterators in-place. When you can fully grok this, you will truly be a Proto master.
// Mutate in-place by advancing all vector iterators the amount
// in the state parameter
struct vector_advance_algo
: proto::or_<
proto::when<
proto::terminal<vector_iterator<_> >
, advance(proto::_value, proto::_state)
>
, proto::when<
proto::terminal<_>
, proto::_void
>
, proto::otherwise<
proto::and_<
proto::fold<
_
, proto::_state
, proto::and_<
vector_advance_algo
, proto::_state
>
>
, proto::_void
>
>
>
{};
The trick to understanding the above is knowing:
proto::_void does nothing and returns void
proto::and_, when used as a transform like this, executes all the specified transforms and returns the result of the last.
After all that, you can now do what you had set out to do: Turn a tree containing vectors into a tree containing iterators, and then advance all the iterators in-place:
proto::literal<std::vector<int> > vec1;
proto::value(vec1).assign(
boost::make_counting_iterator(0)
, boost::make_counting_iterator(16)
);
auto beg = vector_begin_algo()(2 * vec1 + vec1);
proto::display_expr(beg);
vector_advance_algo()(beg, 1u);
proto::display_expr(beg);
vector_advance_algo()(beg, 1u);
proto::display_expr(beg);
I think your code would have worked had you not run into the const weirdness. Also, I think you might have an easier time of it if you write ordinary callables instead of primitive transforms.
Hope this helps.

iterator adapter to iterate just the values in a map?

I'm just getting back into C++ after a couple of years of doing a lot of C#, and recently Objective C.
One thing I've done before is to roll my own iterator adapter for std::map that will deref to just the value part, rather than the key-value pair. This is quite a common and natural thing to do. C# provides this facility with its Keys and Values properties of its Dictionary class. Objective-C's NSDictionary, similarly, has allKeys and allValues.
Since I've been "away", Boost has acquired the Range and ForEach libraries, which I am now using extensively. I wondered if between the two there was some facility to do the same, but I haven't been able to find anything.
I'm thinking of knocking something up using Boost's iterator adapters, but before I go down that route I thought I'd ask here if anyone knows of such a facility in Boost, or somewhere else ready made?
Replacing the previous answer, in case anybody else finds this like I did. As of boost 1.43, there are some commonly used range adaptors provided. In this case, you want boost::adaptors::map_values. The relevant example:
http://www.boost.org/doc/libs/1_46_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html#range.reference.adaptors.reference.map_values.map_values_example
I don't think there's anything out of the box. You can use boost::make_transform.
template<typename T1, typename T2> T2& take_second(const std::pair<T1, T2> &a_pair)
{
return a_pair.second;
}
void run_map_value()
{
map<int,string> a_map;
a_map[0] = "zero";
a_map[1] = "one";
a_map[2] = "two";
copy( boost::make_transform_iterator(a_map.begin(), take_second<int, string>),
boost::make_transform_iterator(a_map.end(), take_second<int, string>),
ostream_iterator<string>(cout, "\n")
);
}
There is a boost range adaptor for exactly this purpose.
See http://www.boost.org/doc/libs/1_53_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html
(This example cribbed from there)
int main(int argc, const char* argv[])
{
using namespace boost::assign;
using namespace boost::adaptors;
std::map<int,int> input;
for (int i = 0; i < 10; ++i)
input.insert(std::make_pair(i, i * 10));
boost::copy(
input | map_values,
std::ostream_iterator<int>(std::cout, ","));
return 0;
}
Continuing David's answer, there's another possibility to put the boile by creating a derived class from boost::transform_iterator. I'm using this solution in my projects:
namespace detail
{
template<bool IsConst, bool IsVolatile, typename T>
struct add_cv_if_c
{
typedef T type;
};
template<typename T>
struct add_cv_if_c<true, false, T>
{
typedef const T type;
};
template<typename T>
struct add_cv_if_c<false, true, T>
{
typedef volatile T type;
};
template<typename T>
struct add_cv_if_c<true, true, T>
{
typedef const volatile T type;
};
template<typename TestConst, typename TestVolatile, typename T>
struct add_cv_if: public add_cv_if_c<TestConst::value, TestVolatile::value, T>
{};
} // namespace detail
/** An unary function that accesses the member of class T specified in the MemberPtr template parameter.
The cv-qualification of T is preserved for MemberType
*/
template<typename T, typename MemberType, MemberType T::*MemberPtr>
struct access_member_f
{
// preserve cv-qualification of T for T::second_type
typedef typename detail::add_cv_if<
std::tr1::is_const<T>,
std::tr1::is_volatile<T>,
MemberType
>::type& result_type;
result_type operator ()(T& t) const
{
return t.*MemberPtr;
}
};
/** #short An iterator adaptor accessing the member called 'second' of the class the
iterator is pointing to.
*/
template<typename Iterator>
class accessing_second_iterator: public
boost::transform_iterator<
access_member_f<
// note: we use the Iterator's reference because this type
// is the cv-qualified iterated type (as opposed to value_type).
// We want to preserve the cv-qualification because the iterator
// might be a const_iterator e.g. iterating a const
// std::pair<> but std::pair<>::second_type isn't automatically
// const just because the pair is const - access_member_f is
// preserving the cv-qualification, otherwise compiler errors will
// be the result
typename std::tr1::remove_reference<
typename std::iterator_traits<Iterator>::reference
>::type,
typename std::iterator_traits<Iterator>::value_type::second_type,
&std::iterator_traits<Iterator>::value_type::second
>,
Iterator
>
{
typedef boost::transform_iterator<
access_member_f<
typename std::tr1::remove_reference<
typename std::iterator_traits<Iterator>::reference
>::type,
typename std::iterator_traits<Iterator>::value_type::second_type,
&std::iterator_traits<Iterator>::value_type::second
>,
Iterator
> baseclass;
public:
accessing_second_iterator():
baseclass()
{}
// note: allow implicit conversion from Iterator
accessing_second_iterator(Iterator it):
baseclass(it)
{}
};
This leads to even cleaner code:
void run_map_value()
{
typedef map<int, string> a_map_t;
a_map_t a_map;
a_map[0] = "zero";
a_map[1] = "one";
a_map[2] = "two";
typedef accessing_second_iterator<a_map_t::const_iterator> ia_t;
// note: specify the iterator adaptor type explicitly as template type, enabling
// implicit conversion from begin()/end()
copy<ia_t>(a_map.begin(), a_map.end(),
ostream_iterator<string>(cout, "\n")
);
}