I'm thinking about a function with signature
template<typename ...Ts>
std::vector<std::tuple<Ts...>> join_vectors(std::vector<Ts>&&...) {
//...
};
but probably a more general one accepting any iterable instead of just std::vector would be good. Probably it would have a signature like this?
template<template<typename> typename C, typename ...Ts>
C<std::tuple<Ts...>> join_vectors(C<Ts>&&...) {
// ...
};
However, I'm not at this level yet in C++ (despite doing the same in Haskell would be relatively easy), hence I seek for help.
Unfortunately, Range-v3's zip is not at my disposal in this case. I'm tagging it because I think those interested in it are in a better position to help me.
For any indexable containers with size something like this is possible:
#include <tuple>
#include <vector>
#include <algorithm>
// Copy from lvalue containers, move from rvalue containers.
template<typename ...Cs>
auto zip(Cs... vecs) {
std::vector<std::tuple<typename std::decay_t<Cs>::value_type...>> vec;
auto len = std::min({vecs.size()...});
vec.reserve(len);
for(std::size_t i=0;i<len;++i){
vec.emplace_back(std::move(vecs[i])...);
}
return vec;
};
//Return vector of tuples with & for non-const vecs and const& if const.
template<typename ...Cs>
auto zip_view(Cs&... vecs) {
std::vector<std::tuple<decltype(vecs[0])...>> vec;
auto len = std::min({vecs.size()...});
vec.reserve(len);
for(std::size_t i=0;i<len;++i){
vec.emplace_back(vecs[i]...);
}
return vec;
};
If the containers have properly implemented move constructors, this solution will copy the containers passed as lvalues and move from rvalue ones.
Very slight downside is that lvalue containers are copied whole first instead of only the individual elements.
Example [Godbolt]
#include <iostream>
#include <memory>
template<typename T, typename...Args>
void print_tuple(const T& first, const Args&... args){
std::cout<<'('<<first;
((std::cout<<','<< args),...);
std::cout<<')';
}
template<typename T>
struct helper{
using fnc_t = void;
};
template<typename...Args>
struct helper<std::tuple<Args...>>{
using fnc_t = void(*)(const Args&... args);
};
template<typename...Args>
struct helper<std::tuple<Args&...>>{
using fnc_t = void(*)(const Args&... args);
};
template<typename T>
using fnc_t2 = typename helper<T>::fnc_t;
template<typename T>
void template_apply(fnc_t2<T> f, const T& tuple){
std::apply(f, tuple);
}
template<typename T>
void print_vec(const std::vector<T>& vec){
for(const auto&e:vec){
template_apply(print_tuple,e);
std::cout<<'\n';
}
}
struct MoveOnlyFoo{
MoveOnlyFoo(int i):m_i(i){}
int m_i;
std::unique_ptr<int> ptr = nullptr;
};
std::ostream& operator<<(std::ostream& o, const MoveOnlyFoo& foo){
return o<<foo.m_i;
}
int main(){
std::vector v1{1,2,3,4,5,6};
std::vector v2{'a','b','c','d','e'};
std::vector v3{1.5,3.5,7.5};
std::vector<MoveOnlyFoo> vmove;
vmove.emplace_back(45);
vmove.emplace_back(46);
vmove.emplace_back(47);
const std::vector v4{-1,-2,-3,-4,-5};
//Move rvalues, copy lvalue.
print_vec(zip(v1,v2,v3, v4, std::move(vmove)));
// This won't work since the elements from the last vector cannot be copied.
//print_vec(zip(v1,v2,v3, v4, vmove));
std::cout<<"View:\n";
//View, provides const& for const inputs, & for non-const
print_vec(zip_view(v1,v2,v3,v4));
std::cout<<"Modify and print:\n";
for(auto& [x,y]: zip_view(v1,v2)){
++x,++y;
}
// Note the view can work with const containers, returns tuple of `const T&`.
print_vec(zip_view(std::as_const(v1),std::as_const(v2)));
}
Output
(1,a,1.5,-1,45)
(2,b,3.5,-2,46)
(3,c,7.5,-3,47)
View:
(1,a,1.5,-1)
(2,b,3.5,-2)
(3,c,7.5,-3)
Modify and print:
(2,b)
(3,c)
(4,d)
(5,e)
(6,f)
Please disregard the readability of the printing code ;)
I modeled it after python zip functionality. Note your initial proposal copies the vectors, so the output is a vector with the values moved from the parameters.
Returning an iterable Cs is harder because you would have to specify how to insert elements into it, iterators cannot do it on their own.
Getting it work with iterators (but returning still a vector) is a chore, but in theory also possible.
Related
Today, I arrived at a situation, where I have a vector of tuples, where the tuples might contain several entries. Now I wanted to convert my vector of tuples to a vector of objects, such that the entries of the tuples will exactly match the uniform initialization of my object.
The following code does the job for me, but it is a bit clumsy. I'm asking myself if it might be possible to derive a generic solution that can construct the Objects if the tuples matches exactly the uniform initialization order of the objects.
This might be a very desirable functionality, when the number of parameters to pass grows.
#include <vector>
#include <tuple>
#include <string>
#include <algorithm>
struct Object
{
std::string s;
int i;
double d;
};
int main() {
std::vector<std::tuple<std::string, int, double>> values = { {"A",0,0.},{"B",1,1.} };
std::vector<Object> objs;
std::transform(values.begin(), values.end(), std::back_inserter(objs), [](auto v)->Object
{
// This might get tedious to type, if the tuple grows
return { std::get<0>(v), std::get<1>(v), std::get<2>(v) };
// This is my desired behavior, but I don't know what magic_wrapper might be
// return magic_wrapper(v);
});
return EXIT_SUCCESS;
}
Provide Object an std::tuple constructor. You can use std::tie to assign your members:
template<typename ...Args>
Object(std::tuple<Args...> t) {
std::tie(s, i, d) = t;
}
Now it gets automatically constructed:
std::transform(values.begin(), values.end(), std::back_inserter(objs),
[](auto v) -> Object {
return { v };
});
To reduce the amount of copying you might want to replace auto v with const auto& v and make the constructor accept a const std::tuple<Args...>& t.
Also, it's good practise to access the source container via const iterator:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs), ...
Here is a non-intrusive version (i.e. not touching Object) that extracts the number of specified data members. Note that this relies on aggregate initialization.
template <class T, class Src, std::size_t... Is>
constexpr auto createAggregateImpl(const Src& src, std::index_sequence<Is...>) {
return T{std::get<Is>(src)...};
}
template <class T, std::size_t n, class Src>
constexpr auto createAggregate(const Src& src) {
return createAggregateImpl<T>(src, std::make_index_sequence<n>{});
}
You invoke it like this:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object { return createAggregate<Object, 3>(v); });
Or, without the wrapping lambda:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
createAggregate<Object, 3, decltype(values)::value_type>);
As #Deduplicator pointed out, the above helper templates implement parts of std::apply, which can be used instead.
template <class T>
auto aggregateInit()
{
return [](auto&&... args) { return Object{std::forward<decltype(args)>(args)...}; };
}
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object { return std::apply(aggregateInit<Object>(), v); });
Since C++17, you might use std::make_from_tuple:
std::transform(values.begin(),
values.end(),
std::back_inserter(objs),
[](const auto& t)
{
return std::make_from_tuple<Object>(t);
});
Note: requires appropriated constructor for Object.
I am creating a function which should take as input iterators to vector
for example:
vector<int> a;
foo(a.begin(),a.end())
The vector can hold any type.
Now the simple way to do this is using templates
template <typename Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it!=last; ++it) {
cout << *it;
}
}
I want to know if there is a way to achieve the same functionality without using templates. Since using Templates would force me to include these functions in Header file of a public API which I don't want to. So I wanted to know is there an alternate way to access the iterators without using Templates.
There are ways not to include the implementation in header files but they are not clean to implement (for instance you should know in advance the instantiations). Read here for more info about this issue:
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
How can I avoid linker errors with my template functions?
For instance in:
foo.h
#ifndef HI_
#define HI_
template<class Iterator>
void foo(Iterator first, Iterator last);
#endif
foo.cpp
#include "stack.h"
using namespace std;
template<class Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it != last; ++it) {
cout << *it << " ";
}
}
template
void foo( std::vector<int>::iterator first, std::vector<int>::iterator last);
template
void foo( std::vector<double>::iterator first, std::vector<double>::iterator last);
Now you can use foo function only for double and int. Other types won't link.
Hope this helps.
This is a long answer. The short answer is "type erasure"; go learn about it.
The long answer is two answers. First I cover "do you just want to be able to iterate over contiguous ints?". Then you want span. This is a really simple form of type erasure that forgets what the exact container is you are working on so long as it is contiguous and over T.
The second answer is if you actually need to deal with multiple types (not just int) and multiple kinds of containers (not just contiguous ones).
The two answers are separated by a line.
The span concept (see gsl::span) is designed for pretty much this reason. It itself is a template (over the type you are working with), but it will be a concrete instance of a template in most interfaces.
Here is a toy version of it:
template<class T>
struct span_t {
T* b = 0;
T* e = 0;
T* begin() const { return b; }
T* end() const { return e; }
span_t(span_t const&)=default;
span_t& operator=(span_t const&)=default;
span_t()=default;
span_t( T* s, T* f ):b(s),e(f) {}
span_t( T* s, std::size_t l):span_t(s, s+l){}
template<std::size_t N>
span_t( T(&arr)[N] ):span_t(arr, N) {}
std::size_t size() const { return end()-begin(); }
bool empty() const { return begin()==end(); }
T& front() const { return *begin(); }
T& back() const { return *(std::prev(end()); }
T* data() const { return begin(); }
span_t without_front( std::size_t N=1 ) const {
return {std::next( begin(), (std::min)(N, size()) ), end()};
}
span_t without_back( std::size_t N=1 ) const {
return {begin(), std::prev(end(), (std::min)(N, size()) )};
}
};
we can augment it with conversion operators
namespace details {
template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type{};
template<class...>using void_t=void;
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void,Ts...>;
template<class C>
using dot_data_r = decltype( std::declval<C>().data() );
template<class C>
using dot_size_r = decltype( std::declval<C>().size() );
template<class C>
using can_dot_data = can_apply< dot_data_r, C >;
template<class C>
using can_dot_size = can_apply< dot_size_r, C >;
can_dot_data detects via SFINAE if .data() is valid to do on an object of type C.
Now we add a constructor:
template<class T,
std::enable_if_t<
can_dot_data<T&>{}
&& can_dot_size<T&>{}
&& !std::is_same<std::decay_t<T>, span_t>{}
, int
> =0
>
span_t( T&& t ): span_t( t.data(), t.size() ) {}
which covers std::vector and std::string and std::array.
Your function now looks like:
void foo(span_t<int> s) {
for (auto&& e:s)
std::cout << s;
}
}
with use:
std::vector<int> a;
foo(a);
now, this only works for contiguous containers of a specific type.
Suppose this is not what you want. Maybe you do need to solve this for a myriad of types, and you don't want to expose everything in the header.
Then what you need to do is known as type erasure.
You need to work out what minimal set of operations you need from the provided types. Then you need to write wrappers that "type erase" these operations down to "typeless" operations.
This goes in the header, or in another helper header.
In the interface of the function, or in a header intermediate helper, you take the incoming types and do the type erasure, then pass the type-erased types into the "real" implementation.
An example of type erasure is std::function. It takes almost anything that can be invoked with a fixed signature, and turns it into a single type-erased type. Everything except how to copy, destroy and invoke an instance of the type is "forgotten" or erased.
For your case:
template <typename Iterator>
void foo(Iterator first, Iterator last) {
for (Iterator it = first; it!=last; ++it) {
cout << *it;
}
}
I see two things that need to be erased down to; iteration, and printing.
struct printable_view_t {
void const* data = 0;
void(*print_f)(std::ostream& os, void const*) = 0;
explicit operator bool()const{return data;}
printable_view_t() = default;
printable_view_t(printable_view_t const&) = default;
template<class T,
std::enable_if_t<!std::is_same<T, printable_view_t>{}, int> =0
>
printable_view_t( T const& t ):
data( std::addressof(t) ),
print_f([](std::ostream& os, void const* pv){
auto* pt = static_cast<T const*>(pv);
os << *pt;
})
{}
std::ostream& operator()(std::ostream& os)const {
print_f(os, data);
return os;
}
friend std::ostream& operator<<(std::ostream& os, printable_view_t p) {
return p(os);
}
};
printable_view_t is an example of type-erasing "I can be printed".
void bar( printable_view_t p ) {
std::cout << p;
}
void test_bar() {
bar(7);
bar(3.14);
bar(std::string("hello world"));
}
The next thing we'd have to do is type erase iteration. This is harder, because we want to type erase iteration over iterating over a printable_view_t type.
Type erasing foreach is a tad easier, and often more efficient.
template<class View>
struct foreach_view_t {
void* data = 0;
void(*func)( std::function<void(View)>, void* ) = 0;
explicit operator bool()const{return data;}
foreach_view_t() = default;
foreach_view_t(foreach_view_t const&) = default;
template<class T,
std::enable_if_t<!std::is_same<std::decay_t<T>, foreach_view_t>{}, int> =0
>
foreach_view_t( T&& t ):
data( const_cast<std::decay_t<T>*>(std::addressof(t)) ),
func([](std::function<void(View)> f, void* pv){
auto* pt = static_cast<std::remove_reference_t<T>*>(pv);
for (auto&& e : *pt)
f(decltype(e)(e));
})
{}
void operator()(std::function<void(View)> f)const{
func(f, data);
}
};
we then daisy chain these together
void foo(foreach_view_t<printable_view_t> x) {
x([](auto p){ std::cout << p; });
}
test code:
std::vector<int> a{1,2,3};
foo(a);
Now much of the header code was "hoisted" into the type erasure types instead of a function template body. But careful choice of the points of type erasure can let you keep what you need from the types precise and narrow, and the logic of how you use those operations private.
As an example, the above code doesn't care where you are printing it to; std::cout was not part of the type erasure.
Live example.
I want to know if there is a way to achieve the same functionality without using templates. [...] I wanted to know is there an alternate way to access the iterators without using Templates.
Yes, if you use C++14, but...
Since using Templates would force me to include these functions in Header file of a public API which I don't want to.
... isn't a useful way for you because it's equivalent to use templates and you have to put it in the header file.
In C++14 you can use a lambda function with auto parameters.
auto foo = [](auto first, auto last)
{ for (auto it = first ; it != last; ++it ) std::cout << *it; };
The autos aren't template (from a formal point of view) but are equivalent and you can't declare foo in the header and develop it in a cpp file.
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.
If I pass the following code through my GCC 4.7 snapshot, it tries to copy the unique_ptrs into the vector.
#include <vector>
#include <memory>
int main() {
using move_only = std::unique_ptr<int>;
std::vector<move_only> v { move_only(), move_only(), move_only() };
}
Obviously that cannot work because std::unique_ptr is not copyable:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete; std::unique_ptr<_Tp, _Dp> = std::unique_ptr]'
Is GCC correct in trying to copy the pointers from the initializer list?
Edit: Since #Johannes doesn't seem to want to post the best solution as an answer, I'll just do it.
#include <iterator>
#include <vector>
#include <memory>
int main(){
using move_only = std::unique_ptr<int>;
move_only init[] = { move_only(), move_only(), move_only() };
std::vector<move_only> v{std::make_move_iterator(std::begin(init)),
std::make_move_iterator(std::end(init))};
}
The iterators returned by std::make_move_iterator will move the pointed-to element when being dereferenced.
Original answer:
We're gonna utilize a little helper type here:
#include <utility>
#include <type_traits>
template<class T>
struct rref_wrapper
{ // CAUTION - very volatile, use with care
explicit rref_wrapper(T&& v)
: _val(std::move(v)) {}
explicit operator T() const{
return T{ std::move(_val) };
}
private:
T&& _val;
};
// only usable on temporaries
template<class T>
typename std::enable_if<
!std::is_lvalue_reference<T>::value,
rref_wrapper<T>
>::type rref(T&& v){
return rref_wrapper<T>(std::move(v));
}
// lvalue reference can go away
template<class T>
void rref(T&) = delete;
Sadly, the straight-forward code here won't work:
std::vector<move_only> v{ rref(move_only()), rref(move_only()), rref(move_only()) };
Since the standard, for whatever reason, doesn't define a converting copy constructor like this:
// in class initializer_list
template<class U>
initializer_list(initializer_list<U> const& other);
The initializer_list<rref_wrapper<move_only>> created by the brace-init-list ({...}) won't convert to the initializer_list<move_only> that the vector<move_only> takes. So we need a two-step initialization here:
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()),
rref(move_only()),
rref(move_only()) };
std::vector<move_only> v(il.begin(), il.end());
The synopsis of <initializer_list> in 18.9 makes it reasonably clear that elements of an initializer list are always passed via const-reference. Unfortunately, there does not appear to be any way of using move-semantic in initializer list elements in the current revision of the language.
Specifically, we have:
typedef const E& reference;
typedef const E& const_reference;
typedef const E* iterator;
typedef const E* const_iterator;
const E* begin() const noexcept; // first element
const E* end() const noexcept; // one past the last element
As mentioned in other answers, the behaviour of std::initializer_list is to hold objects by value and not allow moving out, so this is not possible. Here is one possible workaround, using a function call where the initializers are given as variadic arguments:
#include <vector>
#include <memory>
struct Foo
{
std::unique_ptr<int> u;
int x;
Foo(int x = 0): x(x) {}
};
template<typename V> // recursion-ender
void multi_emplace(std::vector<V> &vec) {}
template<typename V, typename T1, typename... Types>
void multi_emplace(std::vector<V> &vec, T1&& t1, Types&&... args)
{
vec.emplace_back( std::move(t1) );
multi_emplace(vec, args...);
}
int main()
{
std::vector<Foo> foos;
multi_emplace(foos, 1, 2, 3, 4, 5);
multi_emplace(foos, Foo{}, Foo{});
}
Unfortunately multi_emplace(foos, {}); fails as it cannot deduce the type for {}, so for objects to be default-constructed you have to repeat the class name. (or use vector::resize)
Update for C++20:
Using Johannes Schaub's trick of std::make_move_iterator() with C++20's std::to_array(), you can use a helper function like unto make_tuple() etc., here called make_vector():
#include <array>
#include <memory>
#include <vector>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
{
return make_vector( std::to_array({ std::forward<T>(t)... }) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::to_array({ UX{}, UX{}, UX{} }); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v2 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Godbolt.
Similar answer for older C++:
Using Johannes Schaub's trick of std::make_move_iterator() with std::experimental::make_array(), you can use a helper function:
#include <memory>
#include <type_traits>
#include <vector>
#include <experimental/array>
struct X {};
template<class T, std::size_t N>
auto make_vector( std::array<T,N>&& a )
-> std::vector<T>
{
return { std::make_move_iterator(std::begin(a)), std::make_move_iterator(std::end(a)) };
}
template<class... T>
auto make_vector( T&& ... t )
-> std::vector<typename std::common_type<T...>::type>
{
return make_vector( std::experimental::make_array( std::forward<T>(t)... ) );
}
int main()
{
using UX = std::unique_ptr<X>;
const auto a = std::experimental::make_array( UX{}, UX{}, UX{} ); // Ok
const auto v0 = make_vector( UX{}, UX{}, UX{} ); // Ok
//const auto v1 = std::vector< UX >{ UX{}, UX{}, UX{} }; // !! Error !!
}
See it live on Coliru.
Perhaps someone can leverage std::make_array()'s trickery to allow make_vector() to do its thing directly, but I did not see how (more accurately, I tried what I thought should work, failed, and moved on). In any case, the compiler should be able to inline the array to vector transformation, as Clang does with O2 on GodBolt.
This is the solution I like the most.
C++17 version
#include <vector>
#include <memory>
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
container.reserve(sizeof...(Args));
((container.emplace_back(std::forward<Args>(args))), ...);
return container;
}
int main() {
auto vec = BuildVectorFromMoveOnlyObjects<std::unique_ptr<int>>(
std::make_unique<int>(10),
std::make_unique<int>(50));
}
A bit uglier C++11 version
template <typename T, typename ...Args>
std::vector<T> BuildVectorFromMoveOnlyObjects(Args&&... args) {
std::vector<T> container;
using expander = int[];
(void)expander{0, (void(container.emplace_back(std::forward<Args>(args))), 0)... };
return container;
}
An attempt at a simple to-the-point answer for the rest of us.
You can't. It's broken.
Fortunately, array initializers aren't broken.
static std::unique_ptr<SerializerBase> X::x_serializers[] = {
std::unique_ptr<SerializerBase>{
new Serializer<X,int>("m_int",&X::m_int)
},
std::unique_ptr<SerializerBase>{
new Serializer<X,double>("m_double",&X::m_double)
},
nullptr, // lol. template solutions from hell possible here too.
};
If you then want to use that array to initialize a std::vector<std::unique_ptr<T>>, there are endless ways to do so, many of which involve baroquely unpleasant template metaprogramming, all of which can be avoided with a for loop.
Fortunately, using an array instead of a std::vector works in a lot of cases where you really would have preferred to use a std::vector.
Alternately, consider writing a custom::static_vector<T> class that take T*'s in an initializer list, and deletes them in its's destructor. Also not happy, but you need to resign yourself to the fact that std::vector<std::unique_ptr<T>> isn't going to work in reasonable time or with reasonable effort. You can just delete any methods that do a potential move (move and copy constructors,T&operator[]() &c). Or get fancy and implement rudimentary move semantics if you must (but you probably don't).
See [1] for a defense of this, provided for members of the Purist priesthood.
[1] Programming languages are supposed to increase productivity.
Template meta-programming isn't doing that in this case. All I
want is a way to ensure that I don't leak memory allocated in
static initialization into the heap, thereby making it impossible
to use valgrind to verify that I'm not leaking memory.
That's an everyday use-case. And it shouldn't be difficult. Making it remotely complicated only leads to shortcuts down the road.
I've made a small library for this purpose.
run on gcc.godbolt.org
#include <better_braces.hpp>
#include <iostream>
#include <memory>
#include <vector>
int main()
{
std::vector<std::unique_ptr<int>> foo = init{nullptr, std::make_unique<int>(42)};
std::cout << foo.at(0) << '\n'; // 0
std::cout << foo.at(1) << " -> " << *foo.at(1) << '\n'; // 0x602000000010 -> 42
}
Unlike the move_iterator approach, this doesn't necessarily move each element. nullptr is emplaced directly into the vector, without constructing an intermediate std::unique_ptr.
This allows it to work even with non-movable types:
std::vector<std::atomic_int> bar = init{1, 2, 3};
As it has been pointed out, it is not possible to initialize a vector of move-only type with an initializer list. The solution originally proposed by #Johannes works fine, but I have another idea... What if we don't create a temporary array and then move elements from there into the vector, but use placement new to initialize this array already in place of the vector's memory block?
Here's my function to initialize a vector of unique_ptr's using an argument pack:
#include <iostream>
#include <vector>
#include <make_unique.h> /// #see http://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding
template <typename T, typename... Items>
inline std::vector<std::unique_ptr<T>> make_vector_of_unique(Items&&... items) {
typedef std::unique_ptr<T> value_type;
// Allocate memory for all items
std::vector<value_type> result(sizeof...(Items));
// Initialize the array in place of allocated memory
new (result.data()) value_type[sizeof...(Items)] {
make_unique<typename std::remove_reference<Items>::type>(std::forward<Items>(items))...
};
return result;
}
int main(int, char**)
{
auto testVector = make_vector_of_unique<int>(1,2,3);
for (auto const &item : testVector) {
std::cout << *item << std::endl;
}
}
Is there, perhaps in boost, consistent element access semantics which works across containers?
something along the lines of:
element_of(std_pair).get<1>();
element_of(boost_tuple).get<0>();
element_of(pod_array).get<2>();
in principle i can write myself, but I would rather not reinvent the wheel.thanks
Containers have different ways of accessing them because they are inherently different. The closest that you get in the STL are iterators. All of the standard containers have iterators, so you can iterate over them and use the same algorithms on them using those iterators. However, what each iterator contains differs depending on the container (must just have the element, but maps have pairs). And if you're looking at pair as a container, it's not going to fit in with the rest because it doesn't have iterators.
In most cases, using iterators solves the problem. However, it obviously doesn't completely solve the problem, and the STL does not have a solution for it. Boost may, but I'm unaware of one.
The main point, however, is that containers are inherently different and to a great extent are not meant to be interchangeable. By using standard iterators, most containers can be swapped for one another fairly easily. But it doesn't generally make sense to swap one container for another without changing some of the code around it because they act so differently. I believe that Scott Meyers makes a point of this in his book "Effective STL."
If you're really trying to make the various containers interchangeable, I'd suggest rethinking that and looking more closely at what you're doing. Odds are that that's not the best idea. Now, it may very well be a good idea for your particular application - I certainly can't say without knowing anything about it, and you'd be the best judge of that - but in the general case, making containers truly interchangeable is a bad idea. Iterators make it possible to reuse many algorithms on them, but even there, the type of algorithms that you can use on a particular container varies depending on the type of iterators that that container uses (random access, bi-directional, etc.).
So, no, I'm not aware of a pre-existing solution for accessing container elements other than iterators, but generally speaking, I'd advise against attempting it. Containers are not truly interchangeable and are not meant to be.
I'm not aware of such a thing.
You could most probably just implement a free get function for the types you're interested in. Boost.Tuple already has it. std::pair has it in C++0x. And the rest shouldn't be too complicated.
E.g
#include <iostream>
#include <utility>
#include <vector>
#include <boost/tuple/tuple.hpp>
namespace getter
{
template <size_t Index, class Container>
typename Container::reference get(Container& c)
{
return c[Index];
}
template <size_t Index, class Container>
typename Container::const_reference get(const Container& c)
{
return c[Index];
}
template <size_t Index, class T>
T& get(T *arr)
{
return arr[Index];
}
namespace detail {
template <size_t Index, class T, class U>
struct PairTypeByIndex;
template <class T, class U>
struct PairTypeByIndex<0u, T, U>
{
typedef T type;
type& operator()(std::pair<T, U>& p) const { return p.first; }
const type& operator()(const std::pair<T, U>& p) const { return p.first; }
};
template <class T, class U>
struct PairTypeByIndex<1u, T, U>
{
typedef U type;
type& operator()(std::pair<T, U>& p) const { return p.second; }
const type& operator()(const std::pair<T, U>& p) const { return p.second; }
};
}
template <size_t Index, class T, class U>
typename detail::PairTypeByIndex<Index, T, U>::type& get(std::pair<T, U>& p)
{
return detail::PairTypeByIndex<Index, T, U>()(p);
}
template <size_t Index, class T, class U>
const typename detail::PairTypeByIndex<Index, T, U>::type& get(const std::pair<T, U>& p)
{
return detail::PairTypeByIndex<Index, T, U>()(p);
}
using boost::get;
}
int main()
{
boost::tuple<int, int> tuple(2, 3);
std::cout << getter::get<0>(tuple) << '\n';
std::vector<int> vec(10, 1); vec[2] = 100;
std::cout << getter::get<2>(vec) << '\n';
const int arr[] = {1, 2, 3, 4, 5};
std::cout << getter::get<4>(arr) << '\n';
std::pair<int, float> pair(41, 3.14);
++getter::get<0>(pair);
const std::pair<int, float> pair_ref = pair;
std::cout << getter::get<0>(pair_ref) << ' ' << getter::get<1>(pair_ref) << '\n';
}
I'm not aware of any generic accessors that would work across all known definitions of containers in C++. However, Boost.Range can be used as such to some extent.
For better flexibility, you will likely need to implement it yourself. Perhaps scratching something along this:
struct container_accessor { ... }
template <typename Container>
container_accessor make_accessor(Container& c) { ... }
template <typename Container>
container_const_accessor make_accessor(Container const& c) { ... }
where and then specialise container_accessor for all containers you need.