C++ generic insert into std container? - c++

If I have the following program:
#include <vector>
#include <set>
template<class T, class U>
void AddToContainer(T& container, U value)
{
container.push_back(value);
}
int main(char**, int)
{
std::vector<int> v;
AddToContainer(v, 1);
std::set<int> s;
AddToContainer(s, 1);
return 0;
}
How can I make the adding to the container generic? Since std::set hasn't got a push_back but only insert, this will fail to compile.

You could use expression SFINAE with a dummy parameter to check if push_back() works:
template <class C, class V>
auto append(C& container, V&& value, int)
-> decltype(container.push_back(std::forward<V>(value)), void())
{
container.push_back(std::forward<V>(value));
}
template <class C, class V>
void append(C& container, V&& value, ...)
{
container.insert(std::forward<V>(value));
}
which your function will just forward to:
template <class C, class V>
void AddToContainer(C& container, V&& value) {
append(container, std::forward<V>(value), 0);
}
If push_back() is a valid expression, the first overload will be preferred since int is a better match for 0 than ... If push_back() isn't a valid expression, then there's only one viable overload.
Whether this is actually a good idea or not is a separate question.

I believe that all* C++ containers (though not the container adapters like priority_queue) have a version of insert that looks like this:
iterator insert(iterator location, T&& value)
For the sequence collections, the location is the actual location; for associative collections (like map and unordered_map), the iterator is a "hint" parameter (for instance, to help a map insert an element quickly if you already know precisely where it belongs in sorted order). However, providing an invalid hint doesn't cause any invalid behavior, so a valid generic insert for C++ collections would be:
template<C, T>
void insert(C& collection, T&& value) {
collection.insert(collection.end(), std::forward<T>(value));
}
* It looks like forward_list is the only one that doesn't have this method, which makes sense.

C++20 style:
template<typename C, typename V>
requires requires (C& c, V&& v) { c.push_back(std::forward<V>(v)); }
auto AddToContainer(C& container, V&& value) {
return container.push_back(std::forward<V>(value));
}
template<typename C, typename V>
requires (requires (C& c, V&& v) { c.insert(c.end(), std::forward<V>(v)); } &&
!requires(C& c, V&& v) { c.push_back(std::forward<V>(v)); })
auto AddToContainer(C& container, V&& value) {
return container.insert(container.end(), std::forward<V>(value));
}
or more succinct but with worse diagnostics:
template<typename C, typename V>
auto AddToContainer(C& container, V&& value)
{
if constexpr (requires (C& c, V&& v) { c.push_back(std::forward<V>(v)); })
return container.push_back(std::forward<V>(value));
else
return container.insert(container.end(), std::forward<V>(value));
}

If you are not worried about the order of elements inserted in the set,
template<typename Container, typename value>
void addelement(Container& C, value v)
{
std::fill_n(std::inserter(C,C.end()), 1,v);
}
int main()
{
std::vector<int> v;
addelement(v, 2);
addelement(v, 4);
addelement(v, 6);
std::set<int> s;
addelement(s, 8);
addelement(s, 6);
addelement(s, 4);
addelement(s, 8);
std::cout << "Vector elements :: " << std::endl;
for (auto item : v)
std::cout << item << std::endl;
std::cout << "Set elements :: " << std::endl;
for (auto item : s)
std::cout << item << std::endl;
return 0;
}

Related

Generic loop that iterates on both stl map and list (c++)

Is there any way to write a generic loop whcih iterates over values of both say stl map (associative container) and list (non associateve container).
template<typename T>
void foo(T &t)
{
for (auto iter = t.begin(); iter != t.end(); ++iter)
{
printf("%d\n", *iter); // will work for std::list<int> but not for std::map<int, int>
}
}
Thanks
To make it work for std::map - use proper adapter from boost:
foo(someMap | boost::adaptors::map_values);
You might also use Eric Niebler's ranges-v3
foo(someMap | ranges::values);
If you cannot use boost/ranges - use some kind of traits:
template <typename ValueType>
struct ValueGetter
{
static Value& get(ValueType& value)
{
return value;
}
};
template <typename Key, typename Value>
struct ValueGetter<std::pair<const Key, Value>>
{
using ValueType = std::pair<const Key, Value>;
static Value& get(ValueType& value)
{
return value.second;
}
};
template <typename ValueType>
auto& getValue(ValueType& value)
{
return ValueGetter<Value>::get(value);
}
template<typename T>
void foo(T &t)
{
for (auto iter = t.begin(); iter != t.end(); ++iter)
{
printf("%d\n", getValue(*iter));
}
}
Actually, there is already std::for_each (#include <algorithm>) for such purposes. You could feed it with appropriate handler, e. g. in the form of a lambda:
std::vector<int> v;
std::map<int, double> m;
std::for_each(v.begin(), v.end(), [](auto i) { printf("%d\n", i); });
std::for_each(m.begin(), m.end(), [](auto const& i) { printf("%d %f\n", i.first, i.second); });
I do like the way how Aconcagua show it and in most cases, this would be my favorite choice.
To make it more clear and fill the gap about my comment. The author's loop posted here is ok. In this case, the only problematic thing was about the printf(). To solve it, I have suggested something like overloading stream operator() to be able to print out std::map
ostream& operator<<(ostream& os, pair<string, int> it){
os << it.first << " => " << it.second;
}
as you might have realized the iterator in case of the std::map is the pair. Notice, you do not need to specify that for the std::list and the generic loop might look like the following
template<typename T>
void foo(T &t){
for(auto it=t.begin(); it=t.end(); ++it){
cout << *it << endl;
}
}
which is just fine with what was in the question, except printf() => cout. Here, you can also use range-based loops
template<typename T>
void foo(T &t){
for(auto it : t)
cout << it << endl;
}
and finally for_each() on the side with functor or lambda expression.

Cartesian Product using Iterators and Variadic Templates

I'm trying to create a function to generate the Cartesian product of a variable number of input ranges, using the style of the STL. My basic format is that the function accepts a fixed range and the start of an output range, then a variadic number of bidirectional input iterators.
template <
typename BidirectionalIterator,
typename OutputIterator,
typename... Args
>
void cartesian_product(
BidirectionalIterator first,
BidirectionalIterator last,
OutputIterator result,
Args&&... args
);
My idea for the args is that I make a tuple out of it, then I iterate through that tuple to extract the elements. This would require me to follow a few basic steps:
Make a tuple from args
Dereference each iterator in the newly created tuple
Increment each iterator in the tuple in sequence, so that we get all possible combinations of the values in the ranges.
To elaborate on step 3: if we had two sets A = {0, 1} and B = {2, 3}, the Cartesian product A x B = {(0, 2), (0, 3), (1, 2), (1, 3)}.
I can do the first step like:
auto arg_tuple = std::make_tuple(std::forward<Args>(args)...);
The second step, I'm not too sure about. I think I will have somehow push_back elements to a temporary tuple, then set *result equal to that temporary tuple. I was a little inspired by the way that ostream accomplishes this, so I think this could come in handy:
template <typename Tuple, typename T>
auto operator<<(const Tuple &lhs, const T &rhs)
-> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
{
return std::tuple_cat(lhs, std::make_tuple(rhs));
}
The third step is probably pretty trivial. I could combine something like this:
template <typename T>
auto pre_increment(T &x) -> decltype(++x) {
return ++x;
}
with one of the 3,000 implementations of for_each for a tuple that are on here.
Odds are that I'm not correctly leveraging C++14 for this. My education has been entirely on the less-difficult parts of C++11 so far.
If you're tempted to recommend I use boost::fusion for this, thanks, but I would prefer to not use it.
In C++17, we get std::apply(). A possible C++14 implementation is found on that link. We can then implement fmap for a tuple as:
template <class Tuple, class F>
auto fmap(Tuple&& tuple, F f) {
return apply([=](auto&&... args){
return std::forward_as_tuple(f(std::forward<decltype(args)>(args))...);
}, std::forward<Tuple>(tuple));
}
With that:
auto deref_all = fmap(iterators, [](auto it) -> decltype(auto) { return *it; });
auto incr_all = fmap(iterators, [](auto it) { return ++it; });
Here's what I've come up with:
#include <iostream>
#include <tuple>
#include <vector>
template <typename T, typename B>
bool increment(const B& begins, std::pair<T,T>& r) {
++r.first;
if (r.first == r.second) return true;
return false;
}
template <typename T, typename... TT, typename B>
bool increment(const B& begins, std::pair<T,T>& r, std::pair<TT,TT>&... rr) {
++r.first;
if (r.first == r.second) {
r.first = std::get<std::tuple_size<B>::value-sizeof...(rr)-1>(begins);
return increment(begins,rr...);
}
return false;
}
template <typename OutputIterator, typename... Iter>
void cartesian_product(
OutputIterator out,
std::pair<Iter,Iter>... ranges
) {
const auto begins = std::make_tuple(ranges.first...);
for (;;) {
out = { *ranges.first... };
if (increment(begins, ranges...)) break;
}
}
struct foo {
int i;
char c;
float f;
};
int main(int argc, char* argv[]) {
std::vector<int> ints { 1, 2, 3 };
std::vector<char> chars { 'a', 'b', 'c' };
std::vector<float> floats { 1.1, 2.2, 3.3 };
std::vector<foo> product;
cartesian_product(
std::back_inserter(product),
std::make_pair(ints.begin(), ints.end()),
std::make_pair(chars.begin(), chars.end()),
std::make_pair(floats.begin(), floats.end())
);
for (const auto& x : product)
std::cout << x.i << ' ' << x.c << ' ' << x.f << std::endl;
}
The cartesian_product function has a slightly different signature than yours, but it should be straightforward to write a wrapper.
Since the ranges you pass in may potentially have different extents, I'd suggest you pass both begin and end, as in my example.
I recently came up with the solution that allows to invoke a callable object (e.g., lambda) for any combination of the Cartesian product of the input ranges defined by iterators. The lambda makes elements of input ranges accessible by values or by references. Exemplary usage:
std::vector<int> vector = { 1, 2, 3 };
std::set<double> set = { -1.0, -2.0 };
std::string string = "abcd";
bool array[] = { true, false };
std::cout << std::boolalpha;
cartesian_product([](const auto& v1, const auto& v2, const auto& v3, const auto& v4){
std::cout << "(" << v1 << ", " << v2 << ", " << v3 << ", " << v4 << ")\n";
},
std::begin(vector), std::end(vector),
std::begin(set), std::end(set),
std::begin(string), std::end(string),
std::begin(array), std::end(array)
);
I haven't found a solution with such a (natural) syntax (the style of the STL you ask for). The cartesian_product function is in my case built upon C++17 std::apply as follows:
template <typename F, typename... Ts>
void cartesian_product_helper(F&& f, std::tuple<Ts...> t) { std::apply(f, t); }
template <typename F, typename... Ts, typename Iter, typename... TailIters>
void cartesian_product_helper(
F&& f, std::tuple<Ts...> t, Iter b, Iter e, TailIters... tail_iters)
{
for (auto iter = b; iter != e; ++iter)
cartesian_product_helper(
std::forward<F>(f), std::tuple_cat(t, std::tie(*iter)), tail_iters...);
}
template <typename F, typename... Iters>
void cartesian_product(F&& f, Iters... iters) {
cartesian_product_helper(std::forward<F>(f), std::make_tuple(), iters...);
}
It's relatively simple - it iterates over all ranges recursively and in each iteration, it appends the reference to the corresponding dereferenced iterator (i.e., range item) to the tuple. When the tuple is complete (has references to items from all levels), then the callable object is invoked and those references from the tuple are used as arguments.
Just I'm not sure whether this is the most efficient way, so any suggestions for improvement would be helpful.
Live demo is here: https://wandbox.org/permlink/lgPlpKXRkPuTtqo8

Implement partially const iterator

I'm implementing a template class of hash table with keys of type K and values of type V in C++11. All content of this table is stored in std::list <std::pair <K,V> >. Now I want to implement iterator and const_iterator for this table in a such way, that the client could modify only the second element of pair through iterator and couldn't modify any element of pair through const_iterator.
My first idea was just to use std::list <std::pair <const K,V> > as a storage and provide the appropriate iterator's of this list. The problem is when I declare this type of std::list, begin() and end() always return const_iterator, and when I try to convert it to iterator using this method, it doesn't work, because erase in libstdc++ receives only iterator as arguments (it's a bug of libstdc++). So I can't cast const_iterator to iterator.
How can I implement such iterators?
I assume here that you have good reasons to use std::list<std::pair<K, V>> for storage, and not std::[unoredered_]map<K, V> which already behaves like you say.
The simplest option is to use Boost's transform iterator:
https://godbolt.org/z/MvKezs8rx
#include<cassert>
#include<iostream>
#include<list>
#include<boost/iterator/transform_iterator.hpp>
template<class K, class V>
struct kv {
auto operator()(std::pair<K, V>& p) const {
return std::pair<K const&, V&>{p.first, p.second};
}
};
template<class Container, class N = typename Container::value_type, typename K = typename N::first_type, typename V = typename N::second_type>
auto begin_as_map(Container& c) {
return boost::make_transform_iterator(c.begin(), kv<K, V>{});
}
template<class Container, class N = typename Container::value_type, typename K = typename N::first_type, typename V = typename N::second_type>
auto end_as_map(Container& c) {
return boost::make_transform_iterator(c.end() , kv<K, V>{});
}
int main() {
std::list<std::pair<std::string, int>> storage = { {"house", 5}, {"car", 3} };
for(auto const& e : storage) {std::cout<< e.first <<" -> "<< e.second << std::endl;}
auto it = begin_as_map(storage);
assert(it->first == "house"); // ok, first is readable
assert(it->second == 5);
// it->first = "bla"; // error, first is not writable
it->second = 7;
std::cout<<" -- "<<std::endl;
for(auto const& e : storage) {std::cout<< e.first <<" -> "<< e.second << std::endl;}
}

Pass vector<reference_wrapper<int> > to vector<int>?

I have a large std::vector<int> a, but I would like to work only on a subset of it. The idea was to create a std::vector<reference_wrapper<int> > refa that only contains the said subset (in the mwe, all elements 1< a < 4). I would then like to pass refa to functions that expect a std::vector<int> or std::vector<int>& as arguments (because I also want to use them with a). a can be pretty large and I want to avoid to do the selection multiple times.
Questions
How do I properly pass refa to the functions? What I want is bar(refa) and foobar(refa) to work.
Is there a better way to solve the problem, without changing the functions (too much)?
Code
#include <functional>
#include <iostream>
#include <vector>
int foo(int &a)
{
a++;
return 0;
}
int bar(std::vector<int> &va)
{
for(auto &vaa : va)
vaa++;
return 0;
}
int foobar(std::vector<int> va)
{
for(auto &vaa : va)
vaa++;
return 0;
}
int main()
{
std::vector<int> a= {1, 2, 3, 4, 5};
std::vector<std::reference_wrapper<int> > refa;
//Fill refa
for(auto &aa : a)
{
if(aa>1 && aa<4) refa.push_back(std::ref(aa));
}
//works
// for(auto &aa : refa)
// aa++;
//works
// bar(a);
//works, a unchanged
// foobar(a);
//works
// for(auto &aa : refa)
// foo(aa);
//works
// for(int &aa : refa)
// foo(aa)
// does not work
// conversion from vector<reference_wrapper<int> > to vector<int>& or vector<int> required
bar(refa);
// foobar(refa);
for(auto &aa : a)
std::cout << aa << std::endl;
return 0;
}
Note
int is only used here to keep the example simple.
I would definitely use iterators especially considering your problem ahead (work on a subset of a vector):
template<class Iterator>
int bar(Iterator begin, Iterator end)
{
for (auto it = begin; it != end; ++it)
(*it)++;
return 0;
}
So that not only you abstract away from the container, but you can also easily pass different iterators from the classical "begin" and "end" iterator to simulate specific ranges:
bar(a.begin() + 2, a.begin() + 4);
For example, with the above code you will visit elements from 1 to 4 (both excluded). And here's the live example.
Your best bet is to make the functions bar and foobar template functions, like this:
template <typename TContainer>
int bar(TContainer& va)
{
for(auto& vaa : va)
vaa++;
return 0;
}
Without redefining your function to accept "types that look like vector", I don't think that there's a way of achieving what you want.
If you don't need a container, don't use a container. Use an iterable range.
A container is both an iterable range, and an owner of its contents.
In the case of a vector, it is a contiguous iterable range and an owner of the contents. Odds are you only need to know if is a random access iterable range in your implementation code.
However, dealing with arbitrary contiguous iterable ranges has a cost, in that you have to put your implementation in a template header file, or do expensive type erasure. Two ways to approach this is to use the fact that you are only accepting sub-ranges of a vector, or use the fact that you are only accepting sub-ranges of a contiguous range.
I like the contiguous range idea myself:
template<typename T>
struct contiguous_range {
T* b; T* e;
contiguous_range( contiguous_range const& ) = default;
contiguous_range():b(nullptr), e(nullptr) {};
contiguous_range& operator=( contiguous_range const& ) = default;
std::size_t size() const { return e-b; }
T* begin() const { return b; } // note, T*
T* end() const { return e; } // note, T*
template<typename U, typename=typename std::enable_if<
sizeof(U)==sizeof(T)
&& std::is_convertible<U*, T*>::value
>::type>
contiguous_range( contiguous_range<U> const& o ):b(o.b), e(o.e) {};
T& operator[]( std::size_t i ) const { return b[i]; }
template<typename A>
contiguous_range( std::vector<T, A> const& v ):b(v.data()), e(v.data()+v.size()) {}
template<typename U, std::size_t N, typename=typename std::enable_if<
sizeof(U)==sizeof(T)
&& std::is_convertible<U*, T*>::value
>::type>
contiguous_range( std::array<U, N> const& a ):b(a.data()), e(a.data()+a.size()) {}
template<typename U, std::size_t N, typename=typename std::enable_if<
sizeof(U)==sizeof(T)
&& std::is_convertible<U*, T*>::value
>::type>
contiguous_range( U(&a)[N] ):b(&a[0]), e((&a[0])+N) {}
template<typename U, typename=typename std::enable_if<
sizeof(U)==sizeof(T)
&& std::is_convertible<U*, T*>::value
>::type>
contiguous_range( U* b_, U* e_ ):b(b_), e(e_) {}
};
template<typename I>
auto contiguous_subrange( I b, I e )
-> contiguous_range<std::iterator_traits<I>::value_type>
{
return {&*b, &*e};
}
template<typename C>
auto contiguous_subrange( C&& c, std::size_t start, std::size_t end )
-> decltype( contiguous_subrange( &c[start], &c[end] ) )
{ return ( contiguous_subrange( &c[start], &c[end] ) ) };
Now, our functions can simply take a contiguous_range<int> or continguos_range<const int>, and they can be implicitly passed a std::vector<int>.
You can also set up subranges of your std::vector that are equally contiguous.
Note that a constiguous_range<int> corresponds to a std::vector<int>&, and a contiguous_range<const int> corresponds to a std::vector<int> const&.

Common code to iterate through different types of collections

Is there an elegant solution to use common code to iterate through hash_map/unordered_map and list/vector collections?
An example:
template<typename collection>
class multicast
{
public:
typedef collection collection_type;
private:
collection_type& m_channels;
public:
multicast(collection_type& channels) : m_channels(channels) { }
void operator ()(const buffer::ptr& head, const buffer::ptr& cnt)
{
for each(collection_type::value_type& ch in m_channels)
ch->send(head, cnt); /* this is where the magic should happen? */
}
}
This code obviously fails to compile when collection_type is unordered_map since collection_type::value_type is a pair so the code that access the actual value should be different: ch.second->send(head, cnt) instead of ch->send(head, cnt). So what would be the most elegant way to get rid of key part when it is not needed?
Yes:
for (auto & x : collection) { do_stuff_with(x); }
Alternatively:
for (auto it = std::begin(collection), end = std::end(collection); it != end; ++it)
{
do_stuff_with(*it);
}
If neither range-based for nor auto are available, you could write a template which takes a container C and use C::value_type and C::iterator; or you could make a template which accepts a pair of iterators of type Iter and uses std::iterator_traits<Iter>::value_type for the element value type.
Thirdly, you can use for_each and a lambda:
std::for_each(colllection.begin(), collection.end(),
[](collection::value_type & x) { do_stuff_with(x); });
To accommodate for both single-element and pair-element containers, you can build a little wrapper:
template <typename T> struct get_value_impl
{
typedef T value_type;
static value_type & get(T & t) { return t; }
};
template <typename K, typename V> struct get_value_impl<std::pair<K, V>>
{
typedef V value_type;
static value_type & get(std::pair<K,V> & p) { return p.second; }
};
template <typename T>
typename get_value_impl<T>::value_type & get_value(T & t)
{
return get_value_impl<T>::get(t);
}
Now you can use get_value(x) or get_value(*it) to get the value only.
The problem is that list/vector contains just a value, while map-s contains a pair of key-value. They are not the same thing, and to iterate the same way you shold at least define what part of the pair you are interested in.
Once defined, you essentially need a "derefence" operation that accepts an iterator, and -in case it has as a value_type a pair, return the second element, oterwise just dereference it.
// default case, returning itself
template<class T>
T& get_val(T& t) { return t; }
// case for pair (derefence for a map iterator)
template<class K, class V>
V& get_val(std::pair<const K, V>& s) { return s.second; }
// iterator dereference
template<class Iter>
decltype(get_val(*Iter()) deref_iter(const Iter& i)
{ return get_val(*i); }
Of course, const_iter version are also required, if needed.
Now:
for(auto i=container.begin(); i!=container-end(); ++i)
do_something_with(deref_iter(i));
will be the same whatever the container.