boost::combine, range-based for and structured bindings - c++

Is there a way to make boost::combine work with structured bindings and range-based for (so that identifiers in the structure binding actually point to containers' elements instead of nested tuples of whatever boost::combine uses under the hood)? The following (live example) fails to compile:
#include <boost/range/combine.hpp>
#include <iostream>
int main()
{
std::vector<int> a{1,2,3};
std::vector<int> b{2,3,4};
for (auto [f, s] : boost::combine(a, b))
{
std::cout << f << ' ' << s << std::endl
}
}

The real answer is to use either boost::tie or grab the range-v3 zip() which actually yields a std::tuple.
The for educational purposes only answer is just to adapt the structured bindings machinery for boost::tuples::cons. That type already has a get() which works with ADL and does the right thing, so all we need to do is provide tuple_size and tuple_element (which ends up being really easy to do since these exact traits already exist in Boost):
namespace std {
template <typename T, typename U>
struct tuple_size<boost::tuples::cons<T, U>>
: boost::tuples::length<boost::tuples::cons<T, U>>
{ };
template <size_t I, typename T, typename U>
struct tuple_element<I, boost::tuples::cons<T, U>>
: boost::tuples::element<I, boost::tuples::cons<T, U>>
{ };
}
But don't actually do that in real code, since really only the type author should opt-in to this kind of thing.
That'll make the structured binding just work.

You can use boost::tie to accomplish this.
#include <boost/range/combine.hpp>
#include <iostream>
int main()
{
std::vector<int> a{1,2,3};
std::vector<int> b{2,3,4};
int f, s;
for (auto var : boost::combine(a, b))
{
boost::tie(f, s) = var;
std::cout << f << ' ' << s << std::endl;
}
}
Demo.

Related

Boost zip-iterator and structured bindings [duplicate]

Is there a way to make boost::combine work with structured bindings and range-based for (so that identifiers in the structure binding actually point to containers' elements instead of nested tuples of whatever boost::combine uses under the hood)? The following (live example) fails to compile:
#include <boost/range/combine.hpp>
#include <iostream>
int main()
{
std::vector<int> a{1,2,3};
std::vector<int> b{2,3,4};
for (auto [f, s] : boost::combine(a, b))
{
std::cout << f << ' ' << s << std::endl
}
}
The real answer is to use either boost::tie or grab the range-v3 zip() which actually yields a std::tuple.
The for educational purposes only answer is just to adapt the structured bindings machinery for boost::tuples::cons. That type already has a get() which works with ADL and does the right thing, so all we need to do is provide tuple_size and tuple_element (which ends up being really easy to do since these exact traits already exist in Boost):
namespace std {
template <typename T, typename U>
struct tuple_size<boost::tuples::cons<T, U>>
: boost::tuples::length<boost::tuples::cons<T, U>>
{ };
template <size_t I, typename T, typename U>
struct tuple_element<I, boost::tuples::cons<T, U>>
: boost::tuples::element<I, boost::tuples::cons<T, U>>
{ };
}
But don't actually do that in real code, since really only the type author should opt-in to this kind of thing.
That'll make the structured binding just work.
You can use boost::tie to accomplish this.
#include <boost/range/combine.hpp>
#include <iostream>
int main()
{
std::vector<int> a{1,2,3};
std::vector<int> b{2,3,4};
int f, s;
for (auto var : boost::combine(a, b))
{
boost::tie(f, s) = var;
std::cout << f << ' ' << s << std::endl;
}
}
Demo.

C++ map key to object

Hi is there a container where a key is a typename and value is an object/instance in boost or std???
What I want to achieve is I have a object pool for each data type and when I want to construct that object I want to just fetch by Key. I already have working code but I would be happier if i used something more standard.
Currently I have a code like this:
template<size_t index, size_t counter, typename T0, typename ...T>
struct PoolBuilderInternal
{
typedef typename boost::mpl::insert<
typename PoolBuilderInternal<index - 1, counter + 1, T...>::m
, boost::mpl::pair<T0, std::integral_constant<size_t, counter> > >::type m;
};
template<size_t counter, typename T0, typename ...T>
struct PoolBuilderInternal<1, counter, T0, T...>
{
typedef typename boost::mpl::map<boost::mpl::pair<T0, std::integral_constant<size_t, counter> > > m;
};
template<typename ...T>
struct Pools
{
std::tuple<
boost::object_pool<T>...> m_pools;
typedef typename PoolBuilderInternal<sizeof...(T), 0, T...>::m poolType;
template<typename T>
boost::object_pool<T>& GetPool()
{
return std::get< boost::mpl::at<poolType, T>::type::value>(m_pools);
}
};
Pools<int, std::string, int64_t> m_pools;
m_pools.Get<int>();
EDIT: What I want is a COMPILE-TIME map. You can imagine a std::tuple<> but some that wouldnt not be accessed by index std::get<0,1,2>... but rather by a key (?std::tuple_map)
If types in the pool are unique use c++ 14 std::get< T >(std::tuple(s))
#include <iostream>
#include <string>
#include <tuple>
struct A
{
int value = 17;
};
int main()
{
auto t = std::make_tuple(1, std::string{"Foo"}, 3.14, A{});
std::cout << "(" << std::get<int>(t) << ", "
<< std::get<std::string>(t)
<< ", " << std::get<double>(t)
<< ", " << std::get<A>(t).value << ")\n";
}
If I understand this question right (and I'm not sure I do), what you really want is some kind of class factory, and that, in various forms, is a well-known design pattern because it allows users of the factory to construct objects whose constructors (and indeed types, quite often, when a class hierarchy is involved) are unknown or off-limits to them.
On that basis, I humbly offer you the following proof-of-concept code. Please note that I threw this together in rather a hurry and it's probably not optimal. I'm sure more is possible, including passing parameters to the relevant constructors to make_string() and make_foo() from the call site (e.g. factory [t_string] ("My string"). I'll look into that when I have time, if you show any interest in this post.
OK, so here's your class factory. You should be able to apply it to any types, including boost types. As coded, any parameters that need to be passed to the object in question are currently defined when the factory function (e.g. make_string) is added to the map (which is probably not ideal). These factory functions also could / should be lambdas. Again, I'll add that in later.
#include <functional>
#include <unordered_map>
#include <variant>
#include <iostream>
struct Foo
{
Foo (int x) : x (x) { }
int x;
};
enum ObjectType { t_string, t_foo }; // ...
using all_possible_types = std::variant <std::string, Foo>; // ...
static all_possible_types make_string (const std::string& s)
{
std::cout << "make_string " << s << "\n";
return all_possible_types (std::string (s));
}
static all_possible_types make_foo (int x)
{
std::cout << "make_foo " << x << "\n";
return all_possible_types (Foo (x));
}
// ...
int main()
{
std::unordered_map <ObjectType, std::function <all_possible_types ()>> factory;
factory.insert ({t_string, std::bind (make_string, "Initial string value")});
factory.insert ({t_foo, std::bind (make_foo, 42)});
// ...
all_possible_types variant_string = factory [t_string] ();
std::cout << std::get <std::string> (variant_string) << "\n\n";
all_possible_types variant_foo = factory [t_foo] ();
std::cout << std::get <Foo> (variant_foo).x << "\n";
}
Output:
make_string Initial string value
Initial string value
make_foo 42
42
Live demo.
As I say, this doesn't look like much now but I will improve it later. In the meantime, I suggest you take a look at it to get your head around what I'm doing here.

struct to/from std::tuple conversion

Assuming I have struct and std::tuple with same type layout:
struct MyStruct { int i; bool b; double d; }
using MyTuple = std::tuple<int,bool,double>;
Is there any standartized way to cast one to another?
P.S. I know that trivial memory copying can do the trick, but it is alignment and implementation dependent
We can use structured bindings to convert a struct into a tuple with a bit of work.
Struct-to-tuple is very awkward.
template<std::size_t N>
struct to_tuple_t;
template<>
struct to_tuple_t<3> {
template<class S>
auto operator()(S&& s)const {
auto[e0,e1,e2]=std::forward<S>(s);
return std::make_tuple(e0, e1, e2);
}
};
Now, write a to_tuple_t for each size you want to support. This gets tedious. Sadly I know of no way to introduce a parameter pack there.
template<std::size_t N, class S>
auto to_tuple(S&& s) {
return to_tuple_t<N>{}(std::forward<S>(s));
}
I know of no way to calculate the value of N required either. So you'd have to type the 3 in auto t = to_tuple<3>(my_struct); when you call it.
I am not a master of structured bindings. There is probably a && or & or a decltype that would permit perfect forwarding on these lines:
auto[e0,e1,e2]=std::forward<S>(s);
return std::make_tuple(e0, e1, e2);
but without a compiler to play with, I'll be conservative and make redundant copies.
Converting a tuple into a struct is easy:
template<class S, std::size_t...Is, class Tup>
S to_struct( std::index_sequence<Is...>, Tup&& tup ) {
using std::get;
return {get<Is>(std::forward<Tup>(tup))...};
}
template<class S, class Tup>
S to_struct( Tup&&tup ) {
using T=std::remove_reference_t<Tup>;
return to_struct(
std::make_index_sequence<std::tuple_size<T>{}>{},
std::forward<Tup>(tup)
);
}
SFINAE support based off tuple_size might be good for to_struct.
The above code works with all tuple-likes, like std::pair, std::array, and anything you custom-code to support structured bindings (tuple_size and get<I>).
Amusingly,
std::array<int, 3> arr{1,2,3};
auto t = to_tuple<3>(arr);
works and returns a tuple with 3 elements, as to_tuple is based on structured bindings, which work with tuple-likes as input.
to_array is another possibility in this family.
Unfortunately there is no automatic way to do that, BUT an alternative is adapt the struct to Boost.Fusion sequence. You do this once and for all for each new class.
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
...
struct MyStruct { int i; bool b; double d; }
BOOST_FUSION_ADAPT_STRUCT(
MyStruct,
(int, i)
(bool, b)
(double, d)
)
The use MyStruct as if it where a Fusion.Sequence (it fits generically almost everywhere you already use std::tuple<...>, if you make those functions generic.) As a bonus you will not need to copy your data members at all.
If you really need to convert to std::tuple, after "Fusion-adapting" you can do this:
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/algorithm/transformation/zip.hpp>
...
auto to_tuple(MyStruct const& ms){
std::tuple<int, bool, double> ret;
auto z = zip(ret, ms);
boost::fusion::for_each(z, [](auto& ze){get<0>(ze) = get<1>(ze);});
// or use boost::fusion::copy
return ret;
}
The truth is that std::tuple is a half-backed feature. It is like having STD containers and no algorithms. Fortunatelly we have #include <boost/fusion/adapted/std_tuple.hpp> that allows us to do amazing things.
Full code:
By including the std_tuple.hpp header from Boost.Fusion std::tuple is automatically adapted to a Boost.Fusion sequence, thus the following is possible by using Boost.Fusion as a bridge between your struct and std::tuple:
#include <iostream>
#include <string>
#include <tuple>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/algorithm/auxiliary/copy.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
struct foo
{
std::string a, b, c;
int d, e, f;
};
BOOST_FUSION_ADAPT_STRUCT(
foo,
(std::string, a)
(std::string, b)
(std::string, c)
(int, d)
(int, e)
(int, f)
)
template<std::size_t...Is, class Tup>
foo to_foo_aux(std::index_sequence<Is...>, Tup&& tup) {
using std::get;
return {get<Is>(std::forward<Tup>(tup))...};
}
template<class Tup>
foo to_foo(Tup&& tup) {
using T=std::remove_reference_t<Tup>;
return to_foo_aux(
std::make_index_sequence<std::tuple_size<T>{}>{},
std::forward<Tup>(tup)
);
}
template<std::size_t...Is>
auto to_tuple_aux( std::index_sequence<Is...>, foo const& f ) {
using boost::fusion::at_c;
return std::make_tuple(at_c<Is>(f)...);
}
auto to_tuple(foo const& f){
using T=std::remove_reference_t<foo>;
return to_tuple_aux(
std::make_index_sequence<boost::fusion::result_of::size<foo>::type::value>{},
f
);
}
int main(){
foo f{ "Hello", "World", "!", 1, 2, 3 };
std::tuple<std::string, std::string, std::string, int, int, int> dest = to_tuple(f);
// boost::fusion::copy(f, dest); // also valid but less general than constructor
std::cout << std::get<0>(dest) << ' ' << std::get<1>(dest) << std::get<2>(dest) << std::endl;
std::cout << at_c<0>(dest) << ' ' << at_c<1>(dest) << at_c<2>(dest) << std::endl; // same as above
foo f2 = to_foo(dest);
std::cout << at_c<0>(f2) << ' ' << at_c<1>(f2) << at_c<2>(f2) << std::endl;
}
I will not recommend reinterpret_cast<std::tuple<...>&>(mystructinstance.i) because that will result in negative votes and it is not portable.
Is there any standartized way to cast one to another?
There is no way to "cast" the one to the other.
The easiest may be to use a std::tie to pack the tuple out into the struct;
struct MyStruct { int i; bool b; double d; };
using MyTuple = std::tuple<int,bool,double>;
auto t = std::make_tuple(42, true, 5.1);
MyStruct s;
std::tie(s.i, s.b, s.d) = t;
Demo.
You can further wrap this up in higher level macros or "generator" (make style) functions, e.g;
std::tuple<int, bool, double> from_struct(MyStruct const& src)
{
return std::make_tuple(src.i, src.b, src.d);
}
MyStruct to_struct(std::tuple<int, bool, double> const& src)
{
MyStruct s;
std::tie(s.i, s.b, s.d) = src;
return s;
}
I know that trivial memory copying can do the trick, but it is alignment and implementation dependent?
You mention the "trivial memory copy" would work - only for copying the individual members. So basically, a memcpy of the entire structure to the tuple and vice-versa is not going to always behave as you expect (if ever); the memory layout of a tuple is not standardised. If it does work, it is highly dependent on the implementation.
Tuple to struct conversion is trivial, but backward I think is impossible at current C++ level in general.
#include <type_traits>
#include <utility>
#include <tuple>
namespace details
{
template< typename result_type, typename ...types, std::size_t ...indices >
result_type
make_struct(std::tuple< types... > t, std::index_sequence< indices... >) // &, &&, const && etc.
{
return {std::get< indices >(t)...};
}
}
template< typename result_type, typename ...types >
result_type
make_struct(std::tuple< types... > t) // &, &&, const && etc.
{
return details::make_struct< result_type, types... >(t, std::index_sequence_for< types... >{}); // if there is repeated types, then the change for using std::index_sequence_for is trivial
}
#include <cassert>
#include <cstdlib>
int main()
{
using S = struct { int a; char b; double c; };
auto s = make_struct< S >(std::make_tuple(1, '2', 3.0));
assert(s.a == 1);
assert(s.b == '2');
assert(s.c == 3.0);
return EXIT_SUCCESS;
}
Live example.

Getting type from template template method parameters

I'm trying to make a method that picks a random element from a container type, like std::vector. Before, I was using this:
std::string pick_random(std::vector<std::string> c) {
int r = std::rand() % ids.size() + 1;
auto it = c.begin();
std::advance(it, r);
return *it;
}
which, as far as I could tell, worked fine. That's not to say it is fine, just that it appeared to be.
I soon had to do the same thing for another container, so I tried using template template arguments to make the method generic:
template <template<typename element_t> container_t>
element_t pick_random(container_t from) { /* ... */ }
This, however, throws an error:
element_t does not name a type
I think my intent is clear enough, but to restate it: I'm trying to get the element type of the list. I could have a separate template parameter, but then it can't properly infer the type. I've tried various different versions, but none work.
container_t is not a type, container_t<T> is.
You may use the following:
template <template<typename, typename...> C, typename T, typename...Ts>
T pick_random(const C<T, Ts...>& from);
as for std::vector, you have allocator: std::vector<T, Alloc>.
In C++14, you may simply use auto
template <typename C>
auto pick_random(const C& from) { /* ... */ }
I don't think that "template template arguments" are required here,
you could simply use the value_type from the container:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <list>
template <typename T>
typename T::value_type pick_random(T& from) {
int r = std::rand() % from.size();
auto it = from.begin();
std::advance(it, r);
return *it;
}
int main() {
std::srand(std::time(0));
std::vector<std::string> words {"the", "frogurt", "is", "also", "cursed"};
std::list<int> numbers {1, 2, 3, 4, 5};
std::cout << "words: " << pick_random(words) << std::endl;
std::cout << "numbers: " << pick_random(numbers) << std::endl;
}
value_type - the type of the values that can be obtained by dereferencing the iterator.
Source: http://en.cppreference.com/w/cpp/iterator/iterator_traits
Even better would be to avoid the arbitrary restriction on class templates. After all, why not be able to pick an element from a raw array? In order to correctly name the type in C++11, we'd have to get the result of an unqualified call to begin, which we can get via:
namespace detail {
using std::begin;
template <typename C>
auto adl_begin(C&& c) -> decltype(begin(std::forward<C>(c))) {
return begin(std::forward<C>(c));
}
}
using detail::adl_begin;
And then use that to deduce the element_type from an arbitrary container:
template <typename C>
auto pick_random(C& container) -> decltype(*adl_begin(container))
{ /* rest as before */ }
Side-note: take your container by reference, not by value.
If you're only using standard library containers then you can get the stored type out of them by using container_t::value_type.
template <typename container_t>
typename container_t::value_type pick_random(container_t& container)
{ ... }

Use template to apply a function template

If the following example were C++ it would contain non-sensical gibberish so I'll define the example to be written in pseudocode (and hence correct). It strongly hints at what I want to do in C++.
#include <vector>
template<class T>
void increment(T& x)
{
++x;
}
template<template<class> class F>
struct Apply
{
template<class T>
void operator()(std::vector<T>& v)
{
for (auto& x : v)
F<T>(x);
}
};
template<template<class> class F, class T>
void apply(F<T> f, std::vector<T>& v)
{
for (auto& x : v)
f(x);
}
int main()
{
std::vector<int> v{1,2,3};
// apply increment function to v
// maybe this?
Apply<increment> a;
a(v);
// hmm... or this?
apply(increment, v);
}
I don't know how to turn this into C++ such that:
increment is a function and not a function object.
The parameter of increment is either deduced or supplied by Apply/apply.
Apply/apply does not know about the name increment.
I can satisfy two out of the three but I'm not sure how to satisfy all three at once. The problem I run into is the apparent need for using a function template as a template template parameter which my compiler doesn't like. Still, it certainly seems possible to get this to work even if that particular route is off limits.
How can it be done?
Edit: I hate to change the problem but I didn't do a great job of trying to formally state requirements. Just pretend you're the author of apply but you're not the author of increment. You're stuck with increment as is.
You seem to be mixing up the type of a function and the function itself.
Writing Apply<increment> in this case does not make sense since increment is the name of the function and not its type.
Furthermore you cannot use a templated function like this without specifying its templated types. But a workaround is to use a generic lambda instead.
Here is a working example
#include <vector>
#include <iostream>
using std::cout;
using std::vector;
template<class T>
void increment(T& x)
{
++x;
}
template<class T>
void print(const T& t) {
for(auto&& v : t)
cout << v << " ";
cout << std::endl;
}
template<typename T, typename F>
void apply(T& container, F function) {
for(auto& v : container) {
function(v);
}
}
int main()
{
vector<int> v{1,2,3};
print(v);
// To retrieve a function pointer you must specify the type
apply(v, &increment<int>);
print(v);
// If your using c++14 you can use a generic lambda
apply(v, [](auto& t) { increment(t); });
print(v);
}
Simple: Drop the whole lot.
template<class F, class T>
void apply(T& v, F f)
{
for (auto& x : v)
f(x);
}
int main()
{
std::vector<int> v{1,2,3};
apply(v, [](int& i) { ++i; });
auto a = [](std::vector<int>& v) {
apply(v, [](int& i) { ++i; });
};
a(v);
}
You're just reinventing lambdas but worse. Functional programming in C++ is best done with function objects because regular functions have shit semantics, and we have language features explicitly for the purpose of making function objects easily, so use them.
As a commenter pointed out, this is also basically just std::transform but overly specific, and std::transform can also take a lambda.
Don't bother trying to functional with passing functions- it can't be done, at least not with a competitive code quality and volume. Use function objects and especially lambdas. This is literally what they're for.