Resize recursive nested vector in template - c++

I'm trying to make a template function that resizes a nested vector in all it's dimensions.
Pretty much like this: resizing multidimensional vector , but for an arbitrary nr. of dims.
(I suppose) The function would (at least) accept a reference to the vector (or vector<vector<T>> or v<v<v<T>>>, etc.) and a vector with the desired sizes. I now also have in index in the sizes vector, but it's probably not needed.
So far, this is what I ended up with (could be completely wrong):
template<typename V> void resize(vector<V> & V1, vector<int32_t> t, int32_t index) {
int32_t current_size=t.at(index);
cout << "resize dim [" << index << "] to size " << current_size <<endl ;
++index;
if (index < t.size()) {
// for each element ??
// for( int i = 0 ; i < V1.size(); i++ ) { resize (V1.at(i), t, index); } // doesn't work
// for( auto const& e : V1 ) { resize (e, t, index); } // doesn't work
// resize( V1, t, index); // recursive call, works, but doesn't do anything
}
I'd like to avoid copies of V1 or any of it's content. I'm not sure if there is a way with an iterator or for loop that passes references. If not, there probably needs to be a forth input to keep the index of V1?
Btw., I'm skipping the first dim on purpose, it is already the correct size.
Any help appreciated.

You're probably looking for something like this (this is c++14-compliant solution, similar one would be a little bit more tricky for c++11 but still possible):
#include <vector>
#include <tuple>
#include <utility>
template <class NestedVectorElement, class Tuple>
void nested_resize(std::vector<std::vector<NestedVectorElement>> &v, Tuple &&t);
template <class VectorElement, class Tuple>
void nested_resize(std::vector<VectorElement> &v, Tuple &&t);
template <class Vector, class Tuple, size_t... Is>
void nested_resize_impl(Vector &v, Tuple &&t, std::index_sequence<Is...>) {
v.resize(std::get<0>(t));
for(auto &nv: v) {
nested_resize(nv, std::forward_as_tuple(std::get<Is + 1>(t)...));
}
}
template <class NestedVectorElement, class Tuple>
void nested_resize(std::vector<std::vector<NestedVectorElement>> &v, Tuple &&t) {
nested_resize_impl(v, t, std::make_index_sequence<std::tuple_size<Tuple>::value - 1>{});
}
template <class VectorElement, class Tuple>
void nested_resize(std::vector<VectorElement> &v, Tuple &&t) {
v.resize(std::get<0>(t));
}
int main() {
std::vector<std::vector<std::vector<int>>> matrix;
nested_resize(matrix, std::make_tuple(3, 2, 3));
matrix.at(2).at(1).at(2) = 0; // at gives you an access only if element exists else throws an exception
}

The real problem here is that each instance of the template needs to generate code for two possibilities: the last dimension of the multidimensional vector, and all other dimensions of the vector. And in the case of the latter, it is necessary to recurse over the following dimensions of the vector, which will lead to an obvious compilation error in the case of the former.
This requires specialization:
#include <vector>
#include <iostream>
template<typename V, typename iter_type>
class resize_dim {
public:
static void resize(V & V1,
iter_type b, iter_type e)
{
if (b == e)
return;
V1.resize(*b);
}
};
template<typename V, typename iter_type>
class resize_dim<std::vector<std::vector<V>>, iter_type> {
public:
static void resize(std::vector<std::vector<V>> & V1,
iter_type b, iter_type e)
{
if (b == e)
return;
V1.resize(*b);
++b;
for (typename std::vector<std::vector<V>>::iterator
vb=V1.begin(),
ve=V1.end(); vb != ve; ++vb)
resize_dim<std::vector<V>, iter_type>::resize(*vb, b, e);
}
};
template<typename V>
void resize(V &v, const std::vector<size_t> &dimensions)
{
resize_dim<V, std::vector<size_t>::const_iterator>
::resize(v, dimensions.begin(), dimensions.end());
}
int main()
{
std::vector<std::vector<std::vector<int>>> v;
std::vector<size_t> d;
d.push_back(3);
d.push_back(3);
d.push_back(3);
resize(v, d);
std::cout << "Ok" << std::endl;
return 0;
}
The sizing vector, giving the size of each dimension should match the number of dimensions in the vector. Extra sizes are ignored. Fewer sizes result only in the leading dimensions getting resized.

This works:
template<typename V> void resizer(V & V1, vector<int32_t> const & t, int32_t index) {}
template<typename V> void resizer(vector<V> & V1, vector<int32_t> const & t, int32_t index) {
int32_t current_size=t.at(index);
V1.resize(t.at(index) );
++index;
if (index < t.size() ) {
for( auto & e : V1 ) {
resizer (e , t, index);
}
}
}
But this is actually a bit better, since we're not needlessly iterating over the last dimension's elements:
template<typename V> void resizer(vector<V> & V1, vector<int32_t> const & t, int32_t index) {
int32_t current_size=t.at(index);
V1.resize(t.at(index) );
}
template<typename V> void resizer(vector<std::vector<V>> & V1, vector<int32_t> const & t, int32_t index) {
int32_t current_size=t.at(index);
V1.resize(t.at(index) );
++index;
if (index < t.size() ) {
for( auto & e : V1 ) {
resizer (e , t, index);
}
}
}

Related

convert c multidimensional array to multidimensional c++ vector

i am trying to convert c multidimensional array to multidimensional c++ vector, i mean, to convert something like this int arr[2][3] = {{1,2,3}, {4,5,6}}; into the correspondent vector.
The array isn't necessarily 2D shaped, it could also be something like this:
int arr[2][2][3] = {
{
{1,2,3},
{4,5,6},
},
{
{7,8,9},
{10,11,12},
}
};
initially i thought that something like this would have worked, but it didn't really turned out to be the case because it seems like if std::vector doesn't allows conversions from C arrays.
std::vector<std::any> V(arr);
Then i thought at something like function recursion, this is my attempt, that (i don't know why!) throws error: no matching function for call to 'length' .
#include <iostream>
#include <type_traits>
#include <vector>
#include <any>
// Get the lenght of a classic C array.
template <class T, unsigned S>
inline unsigned length(const T (&v)[S]) {
return S;
};
// Check wether the input is a classic C array or not.
template <class T>
bool is(const T& t) {
return std::is_array_v<T>;
};
// Turn the classic C input array to vector.
template <class T>
std::vector<std::any> toVector(const T& t) {
std::vector<std::any> V;
for (int k = 0; k < length(t); k++) {
if (is(t[k])) {
V.push_back(toVector(t[k]));
} else {
V.push_back(t[k]);
}
}
return V;
}
int main() {
int16 a[] = {1,2,3};
auto b = toVector(a);
}
What did i wrong in the second attempt? Alternatively, is there a simpler way to manage to do this?
Also, i think it would be better to convert all the numbers in the vector to a unique given data type, is this possible?
I am using c++11 and g++ as compiler –
Note that i do not know how many dimensions my array has.
The equivalent of a C multidimensional array is a flat C++ vector plus a mumtidimensional array view.
The naive equivalent is a vector of vectors (maybe of vectors), which actually corresponds to a C "jagged" array. The memory layout and performance characteristics will be very different.
There are many multi dimensional array-view implementstions on the web.
template<class A>
struct raw_ptr { using type=A*; };
template<class A, std::size_t N>
struct raw_ptr<A[N]>:raw_ptr<A>{};
template<class A>
using raw_ptr_t = typename raw_ptr<A>::type;
template<class T>
struct array_view;
template<class T, std::size_t D0, std::size_t D1>
struct array_view<T[D0][D1]> {
T(*data)[D1]=0;
constexpr array_view( T(&arr)[D0][D1] ):data(arr) {}
explicit array_view( raw_ptr_t<T> buff ):data(reinterpret_cast<T(*)[D1]>(buff)) {}
constexpr array_view<T[D1]> operator[](std::size_t i)const{
return data[i];
}
};
template<class T, std::size_t D0>
struct array_view<T[D0]> {
constexpr array_view( T(&arr)[D0] ):data(arr) {}
explicit constexpr array_view( T* buff ):data(buff) {}
T* data=0;
constexpr T& operator[](std::size_t i)const{
return data[i];
}
};
to convert a int[4][5][6] you'd do:
int array[4][5][6]={/*whatever*/};
std::vector<int> buff(&array[0][0][0], &array[3][4][5]);
array_view<int[4][5][6]> view{buff.data()};
now, view[a][b][c] is the same as array[a][b][c].
Live example.
template<class Array>
struct wrap_array_in_vector {
using raw_ptr = raw_ptr_t<Array>;
using value_type = std::remove_pointer_t<raw_ptr>;
std::vector<value_type> data;
array_view<Array> view;
wrap_array_in_vector(wrap_array_in_vector const& other):
data(other.data),
view(data.data())
{}
wrap_array_in_vector(wrap_array_in_vector && other):
data(std::move(other.data)),
view(data.data())
{
other.view.data = nullptr; // no longer valid
}
decltype(auto) operator[](std::size_t i)const {
return view[i];
}
wrap_array_in_vector( Array const& arr ):
data( reinterpret_cast<value_type const*>(&arr[0]), reinterpret_cast<value_type const*>(&arr[1]) ),
view(data.data())
{}
};
template<class Array>
wrap_array_in_vector(Array&)->wrap_array_in_vector<Array>;
template<class Array>
wrap_array_in_vector(Array const&)->wrap_array_in_vector<Array>;
this lets you do
wrap_array_in_vector wrapped = array;
and wrapped deduces all of its type information it needs.
This should be close to optimal for conversion to a vector. The part of the description that was misleading was that the sizes are not regular, as they are list-initialized and in this case with int, will be zeros.
#include <type_traits>
#include <vector>
#include <iostream>
template<typename T, std::size_t N>
auto to_vectors( T const (&c_array)[N] ) {
using element_base_type = std::decay_t<T>;
if constexpr( std::is_array_v<T> ) {
using child_t = std::remove_cv_t<std::remove_reference_t<decltype( to_vectors( c_array[0] ) )>>;
auto result = std::vector<child_t>( );
result.reserve( N );
for( auto const & element: c_array ) {
result.push_back( to_vectors( element ) );
}
return result;
} else {
return std::vector<T>( c_array, c_array + N );
}
}
int arr[2][2][3] = {
{
{1,2,3},
{4,5,6},
},
{
{7,8,9},
}
};
auto v0 = to_vectors( arr );
template<typename Vec>
void display( Vec const & vec ) {
if constexpr( std::is_same_v<int, typename Vec::value_type> ) {
std::cout << "elements: {";
for( int e: vec ) {
std::cout << e << ',';
}
std::cout << "}\n";
} else {
std::cout << "element count: " << vec.size( ) << '\n';
for( auto const & child: vec ) {
display( child );
}
}
}
int main( ) {
display( v0 );
}
this will output
element count: 2
element count: 2
elements: {1,2,3,}
elements: {4,5,6,}
element count: 2
elements: {7,8,9,}
elements: {0,0,0,}

Constructing an iterator_range with variadic templates and runtime indices

I have a collection of equally-sized vectors and want to provide an interface for the user to obtain an iterator range over a subset of these vectors.
The following example shows the problematic line inside getRange: its idea is to receive a bunch of types (specifying the types of vectors) and equally many indices (specifying the locations of the vectors). The code compiles, but the problem is that i++ never gets executed as intended, i.e., the call is always with just i (which equals 0). This will also lead to runtime errors via boost::get if the user tries to get distinct types.
This is probably a well-known issue. What's a neat solution to it?
#include <vector>
#include <boost/variant.hpp>
#include <boost/range/combine.hpp>
template <typename... T>
struct VectorHolder
{
template<typename X>
using Iterator = typename std::vector<X>::const_iterator;
std::vector<boost::variant<std::vector<T>...> > vecs_;
template <typename X>
auto begin(int idx) const {
return boost::get<std::vector<X> >(vecs_.at(idx)).cbegin();
}
template <typename X>
auto end(int idx) const {
return boost::get<std::vector<X> >(vecs_.at(idx)).cend();
}
};
template <typename... T, typename VectorHolder>
auto getRange(const VectorHolder& vh, const std::vector<int>& idx)
{
assert(sizeof...(T) == idx.size());
// Fetch a boost::iterator_range over the specified indices
std::size_t i = 0;
std::size_t j = 0;
// PROBLEM: i and j not incremented as intended
return boost::combine(
boost::iterator_range<VectorHolder::Iterator<T>>(
vh.begin<T>(idx[i++]), vh.end<T>(idx[j++]))...);
}
int main()
{
VectorHolder<bool, int, double> vh;
vh.vecs_.push_back(std::vector<int>(5, 5));
vh.vecs_.push_back(std::vector<bool>(5));
vh.vecs_.push_back(std::vector<double>(5, 2.2));
vh.vecs_.push_back(std::vector<int>(5, 1));
const std::vector<int> idx = { 0, 3 };
for (auto t : getRange<int, int>(vh, idx))
{
std::cout << t.get<0>() << " " << t.get<1>() << "\n";
}
}
std::index_sequence helps:
template <typename... Ts, typename VectorHolder, std::size_t ... Is>
auto getRange(const VectorHolder& vh, const std::vector<int>& idx, std::index_sequence<Is...>)
{
assert(sizeof...(Ts) == idx.size());
return boost::combine(
boost::iterator_range<typename VectorHolder::template Iterator<Ts>>(
vh.template begin<Ts>(idx[Is]), vh.template end<Ts>(idx[Is]))...);
}
template <typename... Ts, typename VectorHolder>
auto getRange(const VectorHolder& vh, const std::vector<int>& idx)
{
return getRange<Ts...>(vh, idx, std::index_sequence_for<Ts...>());
}
Demo

Overloading operator [] for N-dimensional structure

I made an N-dimensional structure with vectors and templates:
//----------------N-dimensional vector--------------------------------
template<int dim,typename T> class n_dim_vector {
public:
typedef std::vector<typename n_dim_vector<dim - 1, T>::vector> vector;
};
template<typename T> class n_dim_vector <0, T> {
public:
typedef T vector;
};
It can be instatiaated with different dimnsion-counts and is prt of a class that represent a search space.
template<int dim, typename T> class n_dim_ssc {
private:
typename n_dim_vector<dim, T>::vector searchspace;
};
My problem: I cannot get operator[] right to access searchspace properly, specifically the return type.
I tried:
template<typename V> std::vector<V>& operator[](unsigned i) {
return searchspace[i];
}
T& operator[](unsigned i) {
return searchspace[i];
}
at first, thinking the compiler would derive typename V as whatever type searchspace contained at all but the last level. Thats what T& operator[](unsigned i) was for.
But alas, doen't work this way. And I cannot work out how it would
EDIT Don't fear, I do not access empty memory, the structure is initialized and filled, I just didn't include the code for clarity's sake.
Also, I don't intend to access it with a single integer, I wanted to use searchspace[i][j]..[k]
The way to let compiler deduces the return type is auto:
In C++14:
auto operator[](unsigned i) { return searchspace[i]; }
In C++11:
auto operator[](unsigned i) -> decltype(searchspace[i]) { return searchspace[i]; }
I'm answering to your comment
Feel free to recommend something better, I'd appreciate it.
The following code shows one way to handle the multidimensional vector at once, i.e. non-recursively. It could be improved in several ways which I didn't consider for now (for instance, I wouldn't want to use and pass that many arrays but rather use variadic parameter lists. This however requires much more and more diffcult code, so I'll let it be.)
#include <numeric>
template<size_t Dim, typename T>
struct MultiDimVector
{
std::array<size_t, Dim> Ndim;
std::array<size_t, Dim> stride;
std::vector<T> container;
MultiDimVector(std::array<size_t, Dim> const& _Ndim) : Ndim(_Ndim), container(size())
{
stride[0] = 1;
for (size_t i = 1; i<Dim; ++i)
{
stride[i] = stride[i - 1] * Ndim[i - 1];
}
}
size_t size() const
{
return std::accumulate(Ndim.begin(), Ndim.end(), 1, std::multiplies<size_t>());
}
size_t get_index(std::array<size_t, Dim> const& indices) const
{
//here one could also use some STL algorithm ...
size_t ret = 0;
for (size_t i = 0; i<Dim; ++i)
{
ret += stride[i] * indices[i];
}
return ret;
}
T const& operator()(std::array<size_t, Dim> const& indices) const
{
return container[get_index(indices)];
}
};
You can use it like
MultiDimVector<3, double> v({ 3, 2, 5 }); //initialize vector of dimension 3x2x5
auto a = v({0,1,0}); //get element 0,1,0
But as I wrote, the curly brackets suck, so I'd rewrite the whole thing using variadic templates.
The problem with your approach is that you're not initializing any memory inside the vector and just trying to return non-existent memory spots. Something on the line of the following (WARNING: uncleaned and unrefactored code ahead):
#include <iostream>
#include <vector>
template<int dim,typename T> class n_dim_vector {
public:
typedef std::vector<typename n_dim_vector<dim - 1, T>::vector> vector;
};
template<typename T> class n_dim_vector <0, T> {
public:
typedef T vector;
};
template<int dim, typename T> class n_dim_ssc {
public:
typename n_dim_vector<dim, T>::vector searchspace;
n_dim_ssc() {}
n_dim_ssc(typename n_dim_vector<dim, T>::vector space) : searchspace(space) {}
n_dim_ssc<dim-1, T> operator[](std::size_t i) {
if(searchspace.size() < ++i)
searchspace.resize(i);
return n_dim_ssc<dim-1, T>(searchspace[--i]);
}
typename n_dim_vector<dim, T>::vector get() {
return searchspace;
}
};
template<typename T> class n_dim_ssc<0,T> {
public:
typename n_dim_vector<0, T>::vector searchspace;
n_dim_ssc() {}
n_dim_ssc(typename n_dim_vector<0, T>::vector space) : searchspace(space) {}
typename n_dim_vector<0, T>::vector get() {
return searchspace;
}
};
int main(int argc, char** argv) {
n_dim_ssc<0, int> ea;
int a = ea.get();
n_dim_ssc<1, int> ea2;
auto dd2 = ea2[0].get();
n_dim_ssc<2, int> ea3;
auto dd3 = ea3[0][0].get();
}
Try it out
will work with an accessor method (you can modify this as you want).
Anyway I strongly have to agree with Kerrek: a contiguous memory space accessed in a multi-dimensional array fashion will both prove to be faster and definitely more maintainable/easier to use and read.

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&.

Which C++ Standard Library wrapper functions do you use?

This question, asked this morning, made me wonder which features you think are missing from the C++ Standard Library, and how you have gone about filling the gaps with wrapper functions. For example, my own utility library has this function for vector append:
template <class T>
std::vector<T> & operator += ( std::vector<T> & v1,
const std::vector <T> & v2 ) {
v1.insert( v1.end(), v2.begin(), v2.end() );
return v1;
}
and this one for clearing (more or less) any type - particularly useful for things like std::stack:
template <class C>
void Clear( C & c ) {
c = C();
}
I have a few more, but I'm interested in which ones you use? Please limit answers to wrapper functions - i.e. no more than a couple of lines of code.
Quite often I'd use vector as a set of items in no particular order (and, obviously, when I don't need fast is-this-element-in-the-set checks). In these cases, calling erase() is a waste of time since it will reorder the elements and I don't care about order. That's when the O(1) function below comes in handy - just move the last element at the position of the one you'd want to delete:
template<typename T>
void erase_unordered(std::vector<T>& v, size_t index)
{
v[index] = v.back();
v.pop_back();
}
boost::array
contains(container, val) (quite simple, but convenient).
template<typename C, typename T>
bool contains(const C& container, const T& val) {
return std::find(std::begin(container), std::end(container), val) != std::end(container);
}
remove_unstable(begin, end, value)
A faster version of std::remove with the exception that it doesn't preserve the order of the remaining objects.
template <typename T>
T remove_unstable(T start, T stop, const typename T::value_type& val){
while(start != stop) {
if (*start == val) {
--stop;
::std::iter_swap(start, stop);
} else {
++start;
}
}
return stop;
}
(in the case of a vector of pod types (int, float etc) and almost all objects are removed, std::remove might be faster).
template < class T >
class temp_value {
public :
temp_value(T& var) : _var(var), _original(var) {}
~temp_value() { _var = _original; }
private :
T& _var;
T _original;
temp_value(const temp_value&);
temp_value& operator=(const temp_value&);
};
Ok, since it seems this isn't as straight-forward as I thought, here's an explanation:
In its constructor temp_value stores a reference to a variable and a copy of the variable's original value. In its destructor it restores the referenced variable to its original value. So, no matter what you did to the variable between construction and destruction, it will be reset when the temp_value object goes out of scope.
Use it like this:
void f(some_type& var)
{
temp_value<some_type> restorer(var); // remembers var's value
// change var as you like
g(var);
// upon destruction restorer will restore var to its original value
}
Here's another approach that uses the scope-guard trick:
namespace detail
{
// use scope-guard trick
class restorer_base
{
public:
// call to flag the value shouldn't
// be restored at destruction
void dismiss(void) const
{
mDismissed = true;
}
protected:
// creation
restorer_base(void) :
mDismissed(false)
{}
restorer_base(const restorer_base& pOther) :
mDismissed(pOther.is_dismissed())
{
// take "ownership"
pOther.dismiss();
}
~restorer_base(void) {} // non-virtual
// query
bool is_dismissed(void) const
{
return mDismissed;
}
private:
// not copy-assignable, copy-constructibility is ok
restorer_base& operator=(const restorer_base&);
mutable bool mDismissed;
};
// generic single-value restorer, could be made
// variadic to store and restore several variables
template <typename T>
class restorer_holder : public restorer_base
{
public:
restorer_holder(T& pX) :
mX(pX),
mValue(pX)
{}
~restorer_holder(void)
{
if (!is_dismissed())
mX = mValue;
}
private:
// not copy-assignable, copy-constructibility is ok
restorer_holder& operator=(const restorer_holder&);
T& mX;
T mValue;
};
}
// store references to generated holders
typedef const detail::restorer_base& restorer;
// generator (could also be made variadic)
template <typename T>
detail::restorer_holder<T> store(T& pX)
{
return detail::restorer_holder<T>(pX);
}
It's just a bit more boiler-plate code, but allows a cleaner usage:
#include <iostream>
template <typename T>
void print(const T& pX)
{
std::cout << pX << std::endl;
}
void foo(void)
{
double d = 10.0;
double e = 12.0;
print(d); print(e);
{
restorer f = store(d);
restorer g = store(e);
d = -5.0;
e = 3.1337;
print(d); print(e);
g.dismiss();
}
print(d); print(e);
}
int main(void)
{
foo();
int i = 5;
print(i);
{
restorer r = store(i);
i *= 123;
print(i);
}
print(i);
}
It removes its ability to be used in a class, though.
Here's a third way to achieve the same effect (which doesn't suffer from the problems of potentially throwing destructors):
Implementation:
//none -- it is built into the language
Usage:
#include <iostream>
template <typename T>
void print(const T& pX)
{
std::cout << pX << std::endl;
}
void foo(void)
{
double d = 10.0;
double e = 12.0;
print(d); print(e);
{
double f(d);
double g(e);
f = -5.0;
g = 3.1337;
print(f); print(g);
e = std::move(g);
}
print(d); print(e);
}
int main(void)
{
foo();
int i = 5;
print(i);
{
int r(i);
r *= 123;
print(r);
}
print(i);
}
Not really a wrapper, but the infamous missing copy_if. From here
template<typename In, typename Out, typename Pred>
Out copy_if(In first, In last, Out res, Pred Pr)
{
while (first != last) {
if (Pr(*first)) {
*res++ = *first;
}
++first;
}
return res;
}
template< typename T, std::size_t sz >
inline T* begin(T (&array)[sz]) {return array;}
template< typename T, std::size_t sz >
inline T* end (T (&array)[sz]) {return array + sz;}
Sometimes I feel like I'm in begin() and end() hell. I'd like to have some functions like:
template<typename T>
void sort(T& x)
{
std::sort(x.begin(), x.end());
}
and other similar ones for std::find, std::for_each, and basically all the STL algorithms.
I feel that sort(x) is much quicker to read/understand than sort(x.begin(), x.end()).
I don't use this one nearly as much anymore, but it used to be a staple:
template<typename T>
std::string make_string(const T& data) {
std::ostringstream stream;
stream << data;
return stream.str();
}
Will update with more as I remember them. :P
The utility function in everyones toolbox is of course copy_if. Not really a wrapper though.
Another helper I commonly use is deleter, a functor I use with std::for_each to delete all pointers in a container.
[edit]
Digging through my "sth.h" I also found vector<wstring> StringSplit(wstring const&, wchar_t);
I have a header which puts the following in the "util" namespace:
// does a string contain another string
inline bool contains(const std::string &s1, const std::string &s2) {
return s1.find(s2) != std::string::npos;
}
// remove trailing whitespace
inline std::string &rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// remove leading whitespace
inline std::string &ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// remove whitespace from both ends
inline std::string &trim(std::string &s) {
return ltrim(rtrim(s));
}
// split a string based on a delimeter and return the result (you pass an existing vector for the results)
inline std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss(s);
std::string item;
while(std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
// same as above, but returns a vector for you
inline std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
return split(s, delim, elems);
}
// does a string end with another string
inline bool endswith(const std::string &s, const std::string &ending) {
return ending.length() <= s.length() && s.substr(s.length() - ending.length()) == ending;
}
// does a string begin with another string
inline bool beginswith(const std::string &s, const std::string &start) {
return s.compare(0, start.length(), start) == 0;
}
The infamously missing erase algorithm:
template <
class Container,
class Value
>
void erase(Container& ioContainer, Value const& iValue)
{
ioContainer.erase(
std::remove(ioContainer.begin(),
ioContainer.end(),
iValue),
ioContainer.end());
} // erase
template <
class Container,
class Pred
>
void erase_if(Container& ioContainer, Pred iPred)
{
ioContainer.erase(
std::remove_if(ioContainer.begin(),
ioContainer.end(),
iPred),
ioContainer.end());
} // erase_if
Wrapping sprintf
string example = function("<li value='%d'>Buffer at: 0x%08X</li>", 42, &some_obj);
// 'function' is one of the functions below: Format or stringf
The goal is decoupling formatting from output without getting into trouble with sprintf and its ilk. It's not pretty, but it's very useful, especially if your coding guidelines ban iostreams.
Here is a version which allocates as needed, from Neil Butterworth. [View revision history for Mike's version, which I removed as a subset of the remaining two. It is similar to Neil's, except the latter is exception-safe by using vector instead of delete[]: string's ctor will throw on allocation failure. Mike's also uses the same technique shown later to determine size up front. –RP]
string Format( const char * fmt, ... ) {
const int BUFSIZE = 1024;
int size = BUFSIZE, rv = -1;
vector <char> buf;
do {
buf.resize( size );
va_list valist;
va_start( valist, fmt );
// if _vsnprintf() returns < 0, the buffer wasn't big enough
// so increase buffer size and try again
// NOTE: MSFT's _vsnprintf is different from C99's vsnprintf,
// which returns non-negative on truncation
// http://msdn.microsoft.com/en-us/library/1kt27hek.aspx
rv = _vsnprintf( &buf[0], size, fmt, valist );
va_end( valist );
size *= 2;
}
while( rv < 0 );
return string( &buf[0] );
}
Here is a version which determines the needed size up front, from Roger Pate. This requires writable std::strings, which are provided by popular implementations, but are explicitly required by C++0x. [View revision history for Marcus' version, which I removed as it is slightly different but essentially a subset of the below. –RP]
Implementation
void vinsertf(std::string& s, std::string::iterator it,
char const* fmt, int const chars_needed, va_list args
) {
using namespace std;
int err; // local error code
if (chars_needed < 0) err = errno;
else {
string::size_type const off = it - s.begin(); // save iterator offset
if (it == s.end()) { // append to the end
s.resize(s.size() + chars_needed + 1); // resize, allow snprintf's null
it = s.begin() + off; // iterator was invalidated
err = vsnprintf(&*it, chars_needed + 1, fmt, args);
s.resize(s.size() - 1); // remove snprintf's null
}
else {
char saved = *it; // save char overwritten by snprintf's null
s.insert(it, chars_needed, '\0'); // insert needed space
it = s.begin() + off; // iterator was invalidated
err = vsnprintf(&*it, chars_needed + 1, fmt, args);
*(it + chars_needed) = saved; // restore saved char
}
if (err >= 0) { // success
return;
}
err = errno;
it = s.begin() + off; // above resize might have invalidated 'it'
// (invalidation is unlikely, but allowed)
s.erase(it, it + chars_needed);
}
string what = stringf("vsnprintf: [%d] ", err);
what += strerror(err);
throw runtime_error(what);
}
Public interface
std::string stringf(char const* fmt, ...) {
using namespace std;
string s;
va_list args;
va_start(args, fmt);
int chars_needed = vsnprintf(0, 0, fmt, args);
va_end(args);
va_start(args, fmt);
try {
vinsertf(s, s.end(), fmt, chars_needed, args);
}
catch (...) {
va_end(args);
throw;
}
va_end(args);
return s;
}
// these have nearly identical implementations to stringf above:
std::string& appendf(std::string& s, char const* fmt, ...);
std::string& insertf(std::string& s, std::string::iterator it,
char const* fmt, ...);
The is_sorted utility, to test containers before applying algorithms like include which expect a sorted entry:
template <
class FwdIt
>
bool is_sorted(FwdIt iBegin, FwdIt iEnd)
{
typedef typename std::iterator_traits<FwdIt>::value_type value_type;
return adjacent_find(iBegin, iEnd, std::greater<value_type>()) == iEnd;
} // is_sorted
template <
class FwdIt,
class Pred
>
bool is_sorted_if(FwdIt iBegin, FwdIt iEnd, Pred iPred)
{
if (iBegin == iEnd) return true;
FwdIt aIt = iBegin;
for (++aIt; aIt != iEnd; ++iBegin, ++aIt)
{
if (!iPred(*iBegin, *aIt)) return false;
}
return true;
} // is_sorted_if
Yeah, I know, would be better to negate the predicate and use the predicate version of adjacent_find :)
Definitely boost::addressof
//! \brief Fills reverse_map from map, so that all keys of map
// become values of reverse_map and all values become keys.
//! \note This presumes that there is a one-to-one mapping in map!
template< typename T1, typename T2, class TP1, class TA1, class TP2, class TA2 >
inline void build_reverse_map( const std::map<T1,T2,TP1,TA1>& map
, std::map<T2,T1,TP2,TA2>& reverse_map)
{
typedef std::map<T1,T2,TP1,TA1> map_type;
typedef std::map<T2,T1,TP2,TA2> r_map_type;
typedef typename r_map_type::value_type r_value_type;
for( typename map_type::const_iterator it=map.begin(),
end=map.end(); it!=end; ++it ) {
const r_value_type v(it->second,it->first);
const bool was_new = reverse_map.insert(v).second;
assert(was_new);
}
}
Looking at my stl_util.h, many of the classics (deleter functions, copy_if), and also this one (probably also quite common, but I don't see it given in the responses so far) for searching through a map and returning either the found value or a default, ala get in Python's dict:
template<typename K, typename V>
inline V search_map(const std::map<K, V>& mapping,
const K& key,
const V& null_result = V())
{
typename std::map<K, V>::const_iterator i = mapping.find(key);
if(i == mapping.end())
return null_result;
return i->second;
}
Using the default null_result of a default-constructed V is much as same as the behavior of std::map's operator[], but this is useful when the map is const (common for me), or if the default-constructed V isn't the right thing to use.
Here's my set of extra-utils, built on top of a boost.range'ish std-algo wrapper that you might need for some functions. (that's trivial to write, this is the interesting stuff)
#pragma once
/** #file
#brief Defines various utility classes/functions for handling ranges/function objects
in addition to bsRange (which is a ranged version of the \<algorithm\> header)
Items here uses a STL/boost-style naming due to their 'templatised' nature.
If template variable is R, anything matching range_concept can be used.
If template variable is C, it must be a container object (supporting C::erase())
*/
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/smart_ptr.hpp>
namespace boost
{
struct use_default;
template<class T>
class iterator_range;
#pragma warning(disable: 4348) // redeclaration of template default parameters (this clashes with fwd-decl in boost/transform_iterator.hpp)
template <
class UnaryFunction
, class Iterator
, class Reference = use_default
, class Value = use_default
>
class transform_iterator;
template <
class Iterator
, class Value = use_default
, class Category = use_default
, class Reference = use_default
, class difference = use_default
>
class indirect_iterator;
template<class T>
struct range_iterator;
template <
class Incrementable
, class CategoryOrTraversal = use_default
, class difference = use_default
>
class counting_iterator;
template <class Predicate, class Iterator>
class filter_iterator;
}
namespace orz
{
/// determines if any value that compares equal exists in container
template<class R, class T>
inline bool contains(const R& r, const T& v)
{
return std::find(boost::begin(r), boost::end(r), v) != boost::end(r);
}
/// determines if predicate evaluates to true for any value in container
template<class R, class F>
inline bool contains_if(const R& r, const F& f)
{
return std::find_if(boost::begin(r), boost::end(r), f) != boost::end(r);
}
/// insert elements in range r at end of container c
template<class R, class C>
inline void insert(C& c, const R& r)
{
c.insert(c.end(), boost::begin(r), boost::end(r));
}
/// copy elements that match predicate
template<class I, class O, class P>
inline void copy_if(I i, I end, O& o, const P& p)
{
for (; i != end; ++i) {
if (p(*i)) {
*o = *i;
++o;
}
}
}
/// copy elements that match predicate
template<class R, class O, class P>
inline void copy_if(R& r, O& o, const P& p)
{
copy_if(boost::begin(r), boost::end(r), o, p);
}
/// erases first element that compare equal
template<class C, class T>
inline bool erase_first(C& c, const T& v)
{
typename C::iterator end = boost::end(c);
typename C::iterator i = std::find(boost::begin(c), end, v);
return i != c.end() ? c.erase(i), true : false;
}
/// erases first elements that match predicate
template<class C, class F>
inline bool erase_first_if(C& c, const F& f)
{
typename C::iterator end = boost::end(c);
typename C::iterator i = std::find_if(boost::begin(c), end, f);
return i != end ? c.erase(i), true : false;
}
/// erase all elements (doesn't deallocate memory for std::vector)
template<class C>
inline void erase_all(C& c)
{
c.erase(c.begin(), c.end());
}
/// erase all elements that compare equal
template<typename C, typename T>
int erase(C& c, const T& value)
{
int n = 0;
for (boost::range_iterator<C>::type i = boost::begin(c); i != boost::end(c);) {
if (*i == value) {
i = c.erase(i);
++n;
} else {
++i;
}
}
return n;
}
/// erase all elements that match predicate
template<typename C, typename F>
int erase_if(C& c, const F& f)
{
int n = 0;
for (boost::range_iterator<C>::type i = boost::begin(c); i != boost::end(c);) {
if (f(*i)) {
i = c.erase(i);
++n;
} else {
++i;
}
}
return n;
}
/// erases all consecutive duplicates from container (sort container first to get all)
template<class C>
inline int erase_duplicates(C& c)
{
boost::range_iterator<C>::type i = std::unique(c.begin(), c.end());
typename C::size_type n = std::distance(i, c.end());
c.erase(i, c.end());
return n;
}
/// erases all consecutive duplicates, according to predicate, from container (sort container first to get all)
template<class C, class F>
inline int erase_duplicates_if(C& c, const F& f)
{
boost::range_iterator<C>::type i = std::unique(c.begin(), c.end(), f);
typename C::size_type n = std::distance(i, c.end());
c.erase(i, c.end());
return n;
}
/// fill but for the second value in each pair in range
template<typename R, typename V>
inline void fill_second(R& r, const V& v)
{
boost::range_iterator<R>::type i(boost::begin(r)), end(boost::end(r));
for (; i != end; ++i) {
i->second = v;
}
}
/// applying function to corresponding pair through both ranges, min(r1.size(), r2,size()) applications
template<typename R1, typename R2, typename F>
void for_each2(R1& r1, R2& r2, const F& f)
{
boost::range_iterator<R1>::type i(boost::begin(r1)), i_end(boost::end(r1));
boost::range_iterator<R2>::type j(boost::begin(r2)), j_end(boost::end(r2));
for(;i != i_end && j != j_end; ++i, ++j) {
f(*i, *j);
}
}
/// applying function to corresponding pair through both ranges, min(r1.size(), r2,size()) applications
template<typename R1, typename R2, typename R3, typename F>
void for_each3(R1& r1, R2& r2, R3& r3, const F& f)
{
boost::range_iterator<R1>::type i(boost::begin(r1)), i_end(boost::end(r1));
boost::range_iterator<R2>::type j(boost::begin(r2)), j_end(boost::end(r2));
boost::range_iterator<R3>::type k(boost::begin(r3)), k_end(boost::end(r3));
for(;i != i_end && j != j_end && k != k_end; ++i, ++j, ++k) {
f(*i, *j, *k);
}
}
/// applying function to each possible permutation of objects, r1.size() * r2.size() applications
template<class R1, class R2, class F>
void for_each_permutation(R1 & r1, R2& r2, const F& f)
{
typedef boost::range_iterator<R1>::type R1_iterator;
typedef boost::range_iterator<R2>::type R2_iterator;
R1_iterator end_1 = boost::end(r1);
R2_iterator begin_2 = boost::begin(r2);
R2_iterator end_2 = boost::end(r2);
for(R1_iterator i = boost::begin(r1); i != end_1; ++i) {
for(R2_iterator j = begin_2; j != end_2; ++j) {
f(*i, *j);
}
}
}
template <class R>
inline boost::iterator_range<boost::indirect_iterator<typename boost::range_iterator<R>::type > >
make_indirect_range(R& r)
{
return boost::iterator_range<boost::indirect_iterator<typename boost::range_iterator<R>::type > > (r);
}
template <class R, class F>
inline boost::iterator_range<boost::transform_iterator<F, typename boost::range_iterator<R>::type> >
make_transform_range(R& r, const F& f)
{
return boost::iterator_range<boost::transform_iterator<F, typename boost::range_iterator<R>::type> >(
boost::make_transform_iterator(boost::begin(r), f),
boost::make_transform_iterator(boost::end(r), f));
}
template <class T>
inline boost::iterator_range<boost::counting_iterator<T> >
make_counting_range(T begin, T end)
{
return boost::iterator_range<boost::counting_iterator<T> >(
boost::counting_iterator<T>(begin), boost::counting_iterator<T>(end));
}
template <class R, class F>
inline boost::iterator_range<boost::filter_iterator<F, typename boost::range_iterator<R>::type> >
make_filter_range(R& r, const F& f)
{
return boost::iterator_range<boost::filter_iterator<F, typename boost::range_iterator<R>::type> >(
boost::make_filter_iterator(f, boost::begin(r), boost::end(r)),
boost::make_filter_iterator(f, boost::end(r), boost::end(r)));
}
namespace detail {
template<class T>
T* get_pointer(T& p) {
return &p;
}
}
/// compare member function/variable equal to value. Create using #ref mem_eq() to avoid specfying types
template<class P, class V>
struct mem_eq_type
{
mem_eq_type(const P& p, const V& v) : m_p(p), m_v(v) { }
template<class T>
bool operator()(const T& a) const {
using boost::get_pointer;
using orz::detail::get_pointer;
return (get_pointer(a)->*m_p) == m_v;
}
P m_p;
V m_v;
};
template<class P, class V>
mem_eq_type<P,V> mem_eq(const P& p, const V& v)
{
return mem_eq_type<P,V>(p, v);
}
/// helper macro to define function objects that compare member variables of a class
#define ORZ_COMPARE_MEMBER(NAME, OP) \
template <class P> \
struct NAME##_type \
{ \
NAME##_type(const P&p) : m_p(p) {} \
template<class T> \
bool operator()(const T& a, const T& b) const { \
return (a.*m_p) OP (b.*m_p); \
} \
P m_p; \
}; \
template <class P> \
NAME##_type<P> NAME(const P& p) { return NAME##_type<P>(p); }
#define ORZ_COMPARE_MEMBER_FN(NAME, OP) \
template <class P> \
struct NAME##_type \
{ \
NAME##_type(const P&p) : m_p(p) {} \
template<class T> \
bool operator()(const T& a, const T& b) const { \
return (a.*m_p)() OP (b.*m_p)(); \
} \
P m_p; \
}; \
template <class P> \
NAME##_type<P> NAME(const P& p) { return NAME##_type<P>(p); }
/// helper macro to wrap range functions as function objects (value return)
#define ORZ_RANGE_WRAP_VALUE_2(FUNC, RESULT) \
struct FUNC##_ \
{ \
typedef RESULT result_type; \
template<typename R, typename F> \
inline RESULT operator() (R& r, const F& f) const \
{ \
return FUNC(r, f); \
} \
};
/// helper macro to wrap range functions as function objects (void return)
#define ORZ_RANGE_WRAP_VOID_2(FUNC) \
struct FUNC##_ \
{ \
typedef void result_type; \
template<typename R, typename F> \
inline void operator() (R& r, const F& f) const \
{ \
FUNC(r, f); \
} \
};
/// helper macro to wrap range functions as function objects (void return, one argument)
#define ORZ_RANGE_WRAP_VOID_1(FUNC) \
struct FUNC##_ \
{ \
typedef void result_type; \
template<typename R> \
inline void operator() (R& r) const \
{ \
FUNC(r); \
} \
};
ORZ_RANGE_WRAP_VOID_2(for_each);
ORZ_RANGE_WRAP_VOID_1(erase_all);
ORZ_RANGE_WRAP_VALUE_2(contains, bool);
ORZ_RANGE_WRAP_VALUE_2(contains_if, bool);
ORZ_COMPARE_MEMBER(mem_equal, ==)
ORZ_COMPARE_MEMBER(mem_not_equal, !=)
ORZ_COMPARE_MEMBER(mem_less, <)
ORZ_COMPARE_MEMBER(mem_greater, >)
ORZ_COMPARE_MEMBER(mem_lessequal, <=)
ORZ_COMPARE_MEMBER(mem_greaterequal, >=)
ORZ_COMPARE_MEMBER_FN(mem_equal_fn, ==)
ORZ_COMPARE_MEMBER_FN(mem_not_equal_fn, !=)
ORZ_COMPARE_MEMBER_FN(mem_less_fn, <)
ORZ_COMPARE_MEMBER_FN(mem_greater_fn, >)
ORZ_COMPARE_MEMBER_FN(mem_lessequal_fn, <=)
ORZ_COMPARE_MEMBER_FN(mem_greaterequal_fn, >=)
#undef ORZ_COMPARE_MEMBER
#undef ORZ_RANGE_WRAP_VALUE_2
#undef ORZ_RANGE_WRAP_VOID_1
#undef ORZ_RANGE_WRAP_VOID_2
}
I seem to need a Cartesian product, for example {A, B}, {1, 2} -> {(A,1), (A,2), (B,1), (B,2)}
// OutIt needs to be an iterator to a container of std::pair<Type1, Type2>
template <typename InIt1, typename InIt2, typename OutIt>
OutIt
cartesian_product(InIt1 first1, InIt1 last1, InIt2 first2, InIt2 last2, OutIt out)
{
for (; first1 != last1; ++first1)
for (InIt2 it = first2; it != last2; ++it)
*out++ = std::make_pair(*first1, *it);
return out;
}
I would call such an append function by its name and would use operator+= , operator*= and so on for element-wise operations, such as:
template<typename X> inline void operator+= (std::vector<X>& vec1, const X& value)
{
std::transform( vec1.begin(), vec1.end(), vec1.begin(), std::bind2nd(std::plus<X>(),value) );
}
template<typename X> inline void operator+= (std::vector<X>& vec1, const std::vector<X>& vec2)
{
std::transform( vec1.begin(), vec1.end(), vec2.begin(), vec1.begin(), std::plus<X>() );
}
some other simple and obvious wrappers as implied before:
template<typename X> inline void sort_and_unique(std::vector<X> &vec)
{
std::sort( vec.begin(), vec.end() );
vec.erase( std::unique( vec.begin(), vec.end() ), vec.end() );
}
template<typename X> inline void clear_vec(std::vector<X> &vec)
{
std::vector<X>().swap(vec);
}
template<typename X> inline void trim_vec(std::vector<X> &vec, std::size_t new_size)
{
if (new_size<vec.size())
std::vector<X>(vec.begin(),vec.begin() + new_size).swap(vec);
else
std::vector<X>(vec).swap(vec);
}
Insert a new item and return it, useful for simple move semantics like push_back(c).swap(value) and related cases.
template<class C>
typename C::value_type& push_front(C& container) {
container.push_front(typename C::value_type());
return container.front();
}
template<class C>
typename C::value_type& push_back(C& container) {
container.push_back(typename C::value_type());
return container.back();
}
template<class C>
typename C::value_type& push_top(C& container) {
container.push(typename C::value_type());
return container.top();
}
Pop and return an item:
template<class C>
typename C::value_type pop_front(C& container) {
typename C::value_type copy (container.front());
container.pop_front();
return copy;
}
template<class C>
typename C::value_type pop_back(C& container) {
typename C::value_type copy (container.back());
container.pop_back();
return copy;
}
template<class C>
typename C::value_type pop_top(C& container) {
typename C::value_type copy (container.top());
container.pop();
return copy;
}
IMO there needs to be more functionality for pair:
#ifndef pair_iterator_h_
#define pair_iterator_h_
#include <boost/iterator/transform_iterator.hpp>
#include <functional>
#include <utility>
// pair<T1, T2> -> T1
template <typename PairType>
struct PairGetFirst : public std::unary_function<PairType, typename PairType::first_type>
{
typename typename PairType::first_type& operator()(PairType& arg) const
{ return arg.first; }
const typename PairType::first_type& operator()(const PairType& arg) const
{ return arg.first; }
};
// pair<T1, T2> -> T2
template <typename PairType>
struct PairGetSecond : public std::unary_function<PairType, typename PairType::second_type>
{
typename PairType::second_type& operator()(PairType& arg) const
{ return arg.second; }
const typename PairType::second_type& operator()(const PairType& arg) const
{ return arg.second; }
};
// iterator over pair<T1, T2> -> iterator over T1
template <typename Iter>
boost::transform_iterator<PairGetFirst<typename std::iterator_traits<Iter>::value_type>, Iter>
make_first_iterator(Iter i)
{
return boost::make_transform_iterator(i,
PairGetFirst<typename std::iterator_traits<Iter>::value_type>());
}
// iterator over pair<T1, T2> -> iterator over T2
template <typename Iter>
boost::transform_iterator<PairGetSecond<typename std::iterator_traits<Iter>::value_type>, Iter>
make_second_iterator(Iter i)
{
return boost::make_transform_iterator(i,
PairGetSecond<typename std::iterator_traits<Iter>::value_type>());
}
// T1 -> pair<T1, T2>
template <typename FirstType, typename SecondType>
class InsertIntoPair1st : public std::unary_function<FirstType, std::pair<FirstType, SecondType> >
{
public:
InsertIntoPair1st(const SecondType& second_element) : second_(second_element) {}
result_type operator()(const FirstType& first_element)
{
return result_type(first_element, second_);
}
private:
SecondType second_;
};
// T2 -> pair<T1, T2>
template <typename FirstType, typename SecondType>
class InsertIntoPair2nd : public std::unary_function<SecondType, std::pair<FirstType, SecondType> >
{
public:
InsertIntoPair2nd(const FirstType& first_element) : first_(first_element) {}
result_type operator()(const SecondType& second_element)
{
return result_type(first_, second_element);
}
private:
FirstType first_;
};
#endif // pair_iterator_h_
template <typename T> size_t bytesize(std::vector<T> const& v) { return sizeof(T) * v.size(); }
If you need to use a lot of functions that take pointer + number of bytes, it's always just
fun(vec.data(), bytesize(vec));
Duplicate a string with *:
std::string operator*(std::string s, size_t n)
{
std::stringstream ss;
for (size_t i=0; i<n; i++) ss << s;
return ss.str();
}
One of my favorite is the Transposer that finds a transpose of a tuple of containers of the same size. That is, if you have a tuple<vector<int>,vector<float>>, it converts it into a vector<tuple<int, float>>. Comes handy in XML programming. Here is how I did it.
#include <iostream>
#include <iterator>
#include <vector>
#include <list>
#include <algorithm>
#include <stdexcept>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_io.hpp>
#include <boost/type_traits.hpp>
using namespace boost;
template <class TupleOfVectors>
struct GetTransposeTuple;
template <>
struct GetTransposeTuple<tuples::null_type>
{
typedef tuples::null_type type;
};
template <class TupleOfVectors>
struct GetTransposeTuple
{
typedef typename TupleOfVectors::head_type Head;
typedef typename TupleOfVectors::tail_type Tail;
typedef typename
tuples::cons<typename remove_reference<Head>::type::value_type,
typename GetTransposeTuple<Tail>::type> type;
};
template <class TupleOfVectors,
class ValueTypeTuple =
typename GetTransposeTuple<TupleOfVectors>::type,
unsigned int TUPLE_INDEX = 0>
struct Transposer
: Transposer <typename TupleOfVectors::tail_type,
ValueTypeTuple,
TUPLE_INDEX + 1>
{
typedef typename remove_reference<typename TupleOfVectors::head_type>::type
HeadContainer;
typedef typename TupleOfVectors::tail_type Tail;
typedef Transposer<Tail, ValueTypeTuple, TUPLE_INDEX + 1> super;
typedef std::vector<ValueTypeTuple> Transpose;
Transposer(TupleOfVectors const & tuple)
: super(tuple.get_tail()),
head_container_(tuple.get_head()),
head_iter_(head_container_.begin())
{}
Transpose get_transpose ()
{
Transpose tran;
tran.reserve(head_container_.size());
for(typename HeadContainer::const_iterator iter = head_container_.begin();
iter != head_container_.end();
++iter)
{
ValueTypeTuple vtuple;
this->populate_tuple(vtuple);
tran.push_back(vtuple);
}
return tran;
}
private:
HeadContainer const & head_container_;
typename HeadContainer::const_iterator head_iter_;
protected:
void populate_tuple(ValueTypeTuple & vtuple)
{
if(head_iter_ == head_container_.end())
throw std::runtime_error("Container bound exceeded.");
else
{
vtuple.get<TUPLE_INDEX>() = *head_iter_++;
super::populate_tuple (vtuple);
}
}
};
template <class ValueTypeTuple,
unsigned int INDEX>
struct Transposer <tuples::null_type, ValueTypeTuple, INDEX>
{
void populate_tuple(ValueTypeTuple &) {}
Transposer (tuples::null_type const &) {}
};
template <class TupleOfVectors>
typename Transposer<TupleOfVectors>::Transpose
transpose (TupleOfVectors const & tupleofv)
{
return Transposer<TupleOfVectors>(tupleofv).get_transpose();
}
int main (void)
{
typedef std::vector<int> Vint;
typedef std::list<float> Lfloat;
typedef std::vector<long> Vlong;
Vint vint;
Lfloat lfloat;
Vlong vlong;
std::generate_n(std::back_inserter(vint), 10, rand);
std::generate_n(std::back_inserter(lfloat), 10, rand);
std::generate_n(std::back_inserter(vlong), 10, rand);
typedef tuples::tuple<Vint, Lfloat, Vlong> TupleOfV;
typedef GetTransposeTuple<TupleOfV>::type TransposeTuple;
Transposer<TupleOfV>::Transpose tran =
transpose(make_tuple(vint, lfloat, vlong));
// Or alternatively to avoid copying
// transpose(make_tuple(ref(vint), ref(lfloat), ref(vlong)));
std::copy(tran.begin(), tran.end(),
std::ostream_iterator<TransposeTuple>(std::cout, "\n"));
return 0;
}
Not sure if these qualify as std wrappers, but my commonly used helper functions are:
void split(string s, vector<string> parts, string delims);
string join(vector<string>& parts, string delim);
int find(T& array, const V& value);
void assert(bool condition, string message);
V clamp(V value, V minvalue, V maxvalue);
string replace(string s, string from, string to);
const char* stristr(const char* a,const char*b);
string trim(string str);
T::value_type& dyn(T& array,int index);
T and V here are template arguments. The last function works the same way as []-operator, but with automating resizing to fit needed index.
Similar to what people posted before, I have convenience overloads of algorithms for simplifying passing iterator arguments. I call algorithms like this:
for_each(iseq(vec), do_it());
I overloaded all the algorithms such that they take a single parameter of type input_sequence_range<> instead of the two input iterators (input as in anything that isn't mere output).
template<typename In>
struct input_sequence_range
: public std::pair<In,In>
{
input_sequence_range(In first, In last)
: std::pair<In,In>(first, last)
{ }
};
And this is how iseq() works:
template<typename C>
input_sequence_range<typename C::const_iterator> iseq(const C& c)
{
return input_sequence_range<typename C::const_iterator>(c.begin(),
c.end());
}
Similarly, I have specializations for
const_iterators
pointers (primitive arrays)
stream iterators
any range [begin,end) just for a uniform use: use iseq() for everything
Unordered erase for std::vector. The most efficient way to erase an element from a vector but it does not preserve the order of elements. I didn't see the point of extending it to other containers since most don't have the same penalty for removing items from the middle. It's similar to some other templates already posted but it uses std::swap to move items instead of copying.
template<typename T>
void unordered_erase(std::vector<T>& vec, const typename std::vector<T>::iterator& it)
{
if (it != vec.end()) // if vec is empty, begin() == end()
{
std::swap(vec.back(), *it);
vec.pop_back();
}
}
Signum returns the sign of a type. Returns -1 for negative, 0 for zero and 1 for positive.
template <typename T>
int signum(T val)
{
return (val > T(0)) - (val < T(0));
}
Clamp is pretty self explanatory, it clamps a value so that it lies within the given range. It boggles my mind that the Standard Library includes min and max but not clamp
template<typename T>
T clamp(const T& value, const T& lower, const T& upper)
{
return value < lower ? lower : (value > upper ? upper : value);
}