I have the following situation. Let say we want to implement a sorted array data structure which keeps the array sorted upon insertion. At first attempt, I would do something like:
template<typename T, typename Comparator, Comparator comparator>
SortedArray {
public:
void find(T value);
void insert(T value);
void remove(T value);
}
The argument T is of course for the type of the elements in the array. Then I need a comparator to tell how to compare objects of type T so that I can keep the elements sorted. Since I want to allow for both function pointers (as in classical qsort) as well as function objects and maybe lambda as well, I need to add the template parameter for the comparator.
Now the problem is that I want the compiler to automatically deduce the 2nd Comparator argument based on the 3rd argument. Right now, a typical usage will be exploiting decltype like
int compare_int(int x, int y) {
return x - y;
}
SortedArray<int, decltype(compare_int), compare_int> myArray;
but this doesn't work with lambda and certainly I would love to just write
SortedArray<int, compare_int> myArray;
instead.
Any idea or is it actually possible in C++ at the moment?
You can non type template parameters as follows:
template<typename T, auto C >
class SortedArray
{
private:
std::vector<T> v;
public:
void sort(){ std::sort( v.begin(), v.end(), C );}
void print() { for( auto& el: v ) std::cout << el << std::endl; }
void push(T t){ v.push_back(t);}
};
bool compare_int( int a, int b )
{
return a<b;
}
int main()
{
SortedArray<int, compare_int> sa1;
sa1.push(5);
sa1.push(3);
sa1.push(7);
sa1.sort();
sa1.print();
SortedArray<int, [](int a, int b){ return a<b;} > sa2;
sa2.push(5);
sa2.push(3);
sa2.push(7);
sa2.sort();
sa2.print();
}
As you can see, you can also use a lambda as template parameter.
There is no need to do any template gymnastic with derived template parameters anymore.
Related
guess I have a
class C1 : public B { /*...*/ };
class C2 : public B { /*...*/ };
std::map<std::string, C1> myMap;
std::vector<C2> myVector;
Is there a way (and what would be the syntax) to call a function foo that…
just needs to process the functionalities of B
just needs to process them on all elements of map and vector without caring how they are organized?
std::vector and std::map are both std::_Container_base's but i have no clue how to write the syntax for (pseudocode):
void foo(std::_Container_base-of-Bs)
EDIT: it's _Container_base, not _Tee
The C++ way is to use templates and iterators.
template <typename ForwardIterator>
void process_bs(ForwardIterator first, ForwardIterator last) {
std::for_each(first, last, [](B& b) {
// do something to b here
});
}
For vector, list, deque and set, you can trivially call this using begin and end:
process_bs(v.begin(), v.end());
For map, the element type is pair<const Key, Value>, so you have to adapt the iterators. You can use this with Boost.Range, for example:
#include <boost/range/adaptor/map.hpp>
auto values = m | boost::adaptors::map_values;
process_bs(values.begin(), values.end());
EDIT: The below is a survey on the workarounds, whereas the actual question is not answered therein. So here is the answer: I don't know whether one can process std::_Container_base without knowing if it is a map or a vector.
I couldn't find anything reasonable on the web regarding std::_Container_base, and particularly no C++ standard things, so I would guess it stems from a specific compiler implementation.
vector and map are completely different storage schemes. I suggest you to not use them generically in the same context. That is, from the first you could write a function template
template<typename T> foo(T&& t) { /* takes a vector and a map */ }
but at least when you access operator[], they'll behave differently. That would be unintuitive and error-prone.
However, this doesn't mean you cannot combine the two approaches -- and abstract on size(), operator[](int) and possibly other things like some insertion mechanism.
For example, in some recent code of mine, I have vector-storage scheme (which uses std::vector under the hood), as well as a piecewise constant vector (which uses a std::map). If you want to do this, you can derive those two from a common base class
template<typename T>
struct ContainerBase
{
virtual int size() const = 0;
virtual T operator[](int) const = 0;
virtual void insert(int, T) = 0; //if required
};
and then set up the required functionality in the derived classes Vector and Map.
template<typename T>
struct Vector
{
virtual T operator[](int i) const { return _v[i]; }
virtual T size() const { return _v.size(); }
// ... insert and so on
std::vector<T> _v;
};
template<typename T>
struct Map
{
virtual T operator[](int i) const
{
return *std::lower_bound(i); //add further checks if nothing is found
}
virtual T size() const { return _v.rbegin()->first; // return highest index }
// ... insert and so on
std::map<int, T> _v;
};
The Map implementation is just a sketch. You should choose some reasonable behaviour for it.
With this, it is easy to set up a function foo(ContainerBase&) which works for both Vector and Map.
To use transparently B subclasses into the foo function, you can do this way:
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>
struct B{
int b_member;
};
class C1 : public B { /*...*/ };
class C2 : public B { /*...*/ };
std::map<std::string, C1> myMap;
std::vector<C2> myVector;
// all the magic is into get_B specializations
template<typename E, typename std::enable_if<std::is_base_of<B, E>::value>::type* a = nullptr>
B& get_B(E& elem)
{
return elem;
}
template<typename E, typename std::enable_if<std::is_base_of<B, typename E::second_type>::value>::type* a = nullptr>
B& get_B(E& elem)
{
return elem.second;
}
// foo can call get_B to hide implementation details of the container
template<typename T>
void foo( T& container)
{
for(auto& elem : container)
{
std::cout << get_B(elem).b_member << '\n';
}
}
int main()
{
myVector.resize(10);
myMap["one"] = {};
foo(myMap);
foo(myVector);
}
Thanks to SFINAE, foo uses the correct specialization of get_B to get a reference to the B subclass you want to process.
I've got a few functions, some of which are overloaded and some are templates, ex.:
void fun1 (vector<string> &a, int b);
void fun1 (vector<double> &a, int b);
template <typename t>
void fun2 (t a[], int b);
and so on. Every function I use has a version for 2 data types, one is an array and the other one is a vector (a vector of strings, a vector of doubles, an array of strings and an array of doubles). The question is, can I create a template for an array of pointers? Is there any way of doing it, apart from:
void (*strvecfun[])(vector <string>&, long, long)={fun1, fun2};
void (*dblvecfun[])(vector <double>&, long, long)={fun1, fun2};
void (*strarrfun[])(string [], long, long)={fun1, fun2};
and so on?
You can use
template<typename Func>
struct func_array {
static Func *const data[];
};
template<typename Func>
Func *const func_array<Func>::data[] = { fun1, fun2 };
And later call
func_array<void(std::vector<double>&, long, long)>::data[0](dvec, l1, l2);
func_array<void(std::vector<string>&, long, long)>::data[1](svec, l1, l2);
// ...and so forth
This requires that there are matching overloads for all the signatures you're going to use of all functions you put into the list, naturally.
Instead of having 2 implementations, have one. Have your data take an array_view<double>:
template<class T>
struct array_view {
// can make this private:
T* b = 0; T* e = 0;
// core methods:
T* begin() const { return b; }
T* end() const { return e; }
// utility methods:
size_t size() const { return end()-begin(); }
T& front() const { return *begin(); }
T& back() const { return *std::prev(end()); }
bool empty() const { return begin()==end(); }
// core ctors:
array_view(T* s, T* f):b(s),e(f) {};
array_view()=default;
array_view(array_view const&)=default;
// derived ctors:
array-view(T* s, size_t l):array_view(s, s+l) {};
template<size_t N>
array_view( T(&arr)[N] ):array_view(arr, N) {};
template<size_t N>
array_view( std::array<T,N>&arr ):array_view(arr.data(), N) {};
template<class A>
array_view( std::vector<T,A>& v ):array_view(v.data(), v.size()) {};
// extra ctors that fail to compile if `T` is not const, but
// are mostly harmless even if `T` is not const, and useful if
// `T` is const. We could do fancy work to disable them, but
// I am lazy:
using non_const_T = std::remove_const_t<T>;
template<class A>
array_view( std::vector<non_const_T,A>const& v ):array_view(v.data(), v.size()) {};
template<size_t N>
array_view( std::array<non_const_T,N>const&arr ):array_view(arr.data(), N) {};
array_view( std::initializer_list<non_const_T> il ):array_view(il.data(), il.size()) {};
};
array_view acts like a view into a container, and can be implicitly converted from a number of std containers as well as raw arrays.
void fun1 (array_view<std::string> a);
a.size() tells you how long it is, and it can be iterated over in a for(:) loop even.
std::vector<T>& is far more powerful than what you need. By using array_view, we only expose what you need (access to elements), and thus are able to take both an array and a container.
If you pass in a "real" C style array, it will auto-deduce the length. If you instead pass in a pointer (or a [] really-a-pointer array), you also have to pass the length like:
fun1( {ptr, length} );
Create a function called max that will return the value of the largest element in an array.
The arguments to the function should be the address of the array size.
Make this function into a template so it will work with an array of any numerical types.
I have a std::array and a boost::fusion::vector<X, Y> which I want to pass in to func1(). This function will add a boost::fusion::vector<X, Y> instance to each std::array element.
I have to use fusion::fold() so that I can add the correct number of elements to the fusion::vector<X,Y>, right?
So I currently have something like this:
void func1(){
boost::fusion::vector<X,Y> my_vec;
std::array<boost::fusion::vector<X,Y> > my_array[10];
func2(my_vec, my_array);
}
void func2(boost::fusion::vector<X,Y> my_vec, std::array<boost::fusion::vector<X,Y> > my_array){
//THIS IS THE PART I AM UNSURE ABOUT
for(int k=0; k<10; k++){
//The first two parameters aren't so important- just included to show the idea
my_array[k] = boost::fusion::fold(my_vec, 1, some_struct);
}
}
//This part is irrelevant
struct some_struct
{
typedef int result_type;
template<typename T>
int operator()(int x, T& t) const
{
t = something(x);
//Not sure if this part needs to return a boost::fusion::vector<X, Y>
return x;
}
};
The part I am unsure about is how to use the signature of my_vec in order to create multiple boost::fusion::vector<X,Y> instances and return them back so that I can add to the array in func2().
Could somebody please advise?
EDIT - Just spotted I got the first parameter for fold() wrong, have amended my question.
I'm not sure I understood your question really well so first let's explain what fold is to try to clarify.
In general (not just for fusion) "folding" a function taking two parameters is applying it to each and every element of the vector and to the result of the application of the function to the previous element of the vector. The first element is being given the initial value.
So if I define the function to fold as A f(A, B), the folding of this function will be equivalent to (for 4 elements):
f(f(f(f(A_initial_value, B_0), B_1), B_2), B_3);
(capitalized prefix is there just to enforce type)
Now, more precisely fusion fold. It will fold the function on all the elements inside the boost::fusion::vector<>. As a boost::fusion::vector<X, Y> is equivalent to a std::tuple<X,Y> it will call f on different types:
A_final_value = f(A_initial_value, X_value), Y_value);
So, when you do:
my_array[k] = boost::fusion::fold(my_vec, 1, some_struct);
my_array[k] will receive an numeric value, and that won't compile since you've defined it as fusion::vector<X,Y>
So having trying to clarify fold, I would say no to your question, but I admit that I do not understand what you mean by "add the correct number of elements to the fusion::vector<X,Y>".
EDIT: Updating according what've been said in comment.
The goal isto generate a fibonacci sequence in your std::array<fusion::vector<int, int, int, int>> such as walking each vector of the array will give the fibonacci in the right order.
Using fusion you have to pass a state while iterating through the elements of the vector and so foldwas a good choice.
Here is my suggestion for this (but starting the fibonacci sequence at the second element and not the first, cause I didn't bother to handle the special case... sorry :) ):
template <typename Value>
struct Generator
{
// Easier to read and mandatory for fold
typedef typename std::tuple<Value, Value> result_type;
// The function that generate the fibonacci and update the Value
result_type operator()(result_type previous, Value& elem) const
{
elem = std::get<0>(previous) + std::get<1>(previous);
return std::make_tuple(std::get<1>(previous), elem);
}
};
// Use template to be a bit more generic on array size and vector type
template <typename Vector, size_t array_size, typename Value>
void func2(std::array<Vector, array_size>& array, std::tuple<Value, Value> init)
{
// The state that will be fed across the fold function
auto previous = init;
for (auto& vect: array)
{
// Generate the fibonnaci value for every element of the vector starting
// from where the state is. The return value of fold is the new state
previous = boost::fusion::fold(vect, previous, Generator<Value>());
}
}
// Tool to print the vector
struct Printer
{
template <typename Elem>
void operator()(const Elem& elem) const
{
std::cout << elem << std::endl;
}
};
// Use template to be a bit more generic on array size and vector type
template <typename Vector, size_t array_size, typename Value>
void func1(std::tuple<Value, Value> init)
{
// Create the vector
std::array<Vector, array_size> array;
// FIll it with fibonacci
func2(array, init);
// Print it
for (auto vect: array)
{
boost::fusion::for_each(vect, Printer());
}
}
http://rextester.com/XCXYX58360
I am trying to refactor some code that doesn't use the STL to use the generic algorithms it provide.
I have a struct like this :
struct A {
int i;
//other stuff...
};
// ...
A* array; // array of A objects, sorted by A::i member
int n = ...; // array size
there is then a function that was coded that takes A, n and an integer k, whose purpose is to give me pointers to to the first and the last element of the array that have their i member equal to k.
This is implemented by hand in terms of binary search. I was thinking about using std::equal_range. The problem is that it requires an object of type A to work, and it forces me to introduce a "dummy" A object with it's i member equal to k.
Is there a way to do this using the STL, without having to introduce a "dummy" object?
thanks
Provided your range is sorted according to the value of A::i, this is trivially done with a custom comparator, but note that the comparator must be able compare both ways:
struct AComp
{
bool operator()(int n, A const & a) const { return n < a.i; }
bool operator()(A const & a, int n) const { return a.i < n; }
};
auto p = std::equal_range(array, array + n, 5, AComp());
Now the range [p.first, p.second) contains the elements with A::i equal to 5.
The linked page contains more or less exactly this example.
You may also use std::binary_search() defined in <algorithm> for binary search generally. The prorotype is:
template <class ForwardIterator, class T>
bool binary_search (ForwardIterator first, ForwardIterator last,
const T& val);
or:
template <class ForwardIterator, class T, class Compare>
bool binary_search (ForwardIterator first, ForwardIterator last,
const T& val, Compare comp);
You can define a conversion operator(This is more like a hack, I guess)
class A
{
private:
int i;
public:
A(int x) : i(x){}
operator int(){
return i;
}
};
If this is done you dont have to define operator< in your struct.
I have a POD with about 30 members of various types and I will be wanting to store thousands of the PODs in a container, and then sort that container by one of those members.
For example:
struct Person{
int idNumber;
....many other members
}
Thousands of Person objects which I want to sort by idNumber or by any other member I choose to sort by.
I've been researching this for a while today and it seems the most efficient, or at least, simplest, solution to this is not use struct at all, and rather use tuple for which I can pass an index number to a custom comparison functor for use in std::sort. (An example on this page shows one way to implement this type of sort easily, but does so on a single member of a struct which would make templating this not so easy since you must refer to the member by name, rather than by index which the tuple provides.)
My two-part question on this approach is 1) Is it acceptable for a tuple to be fairly large, with dozens of members? and 2) Is there an equally elegant solution for continuing to use struct instead of tuple for this?
You can make a comparator that stores a pointer to member internaly so it knows which member to take for comparison:
struct POD {
int i;
char c;
float f;
long l;
double d;
short s;
};
template<typename C, typename T>
struct Comp {
explicit Comp(T C::* p) : ptr(p) {}
bool operator()(const POD& p1, const POD& p2) const
{
return p1.*ptr < p2.*ptr;
}
private:
T C::* ptr;
};
// helper function to make a comparator easily
template<typename C, typename T>
Comp<C,T> make_comp( T C::* p)
{
return Comp<C,T>(p);
}
int main()
{
std::vector<POD> v;
std::sort(v.begin(), v.end(), make_comp(&POD::i));
std::sort(v.begin(), v.end(), make_comp(&POD::d));
// etc...
}
To further generalize this, make make_comp take a custom comparator, so you can have greater-than and other comparisons.
1) Is it acceptable for a tuple to be fairly large, with dozens of members?
Yes it is acceptable. However it won't be easy to maintain since all you'll have to work with is an index within the tuple, which is very akin to a magic number. The best you could get is reintroduce a name-to-index mapping using an enum which is hardly maintainable either.
2) Is there an equally elegant solution for continuing to use struct instead of tuple for this?
You can easily write a template function to access a specific struct member (to be fair, I didn't put much effort into it, it's more a proof of concept than anything else so that you get an idea how it can be done):
template<typename T, typename R, R T::* M>
R get_member(T& o) {
return o.*M;
}
struct Foo {
int i;
bool j;
float k;
};
int main() {
Foo f = { 3, true, 3.14 };
std::cout << get_member<Foo, float, &Foo::k>(f) << std::endl;
return 0;
}
From there, it's just as easy to write a generic comparator which you can use at your leisure (I'll leave it to you as an exercise). This way you can still refer to your members by name, yet you don't need to write a separate comparator for each member.
You could use a template to extract the sort key:
struct A
{
std::string name;
int a, b;
};
template<class Struct, typename T, T Struct::*Member>
struct compare_member
{
bool operator()(const Struct& lh, const Struct& rh)
{
return lh.*Member < rh.*Member;
}
};
int main()
{
std::vector<A> values;
std::sort(begin(values), end(values), compare_member<A, int, &A::a>());
}
Maybe you want to have a look at boost::multi_index_container which is a very powerful container if you want to index (sort) object by different keys.
Create a class which can use a pointer to a Person member data to use for comparison:
std::sort(container.begin(), container.end(), Compare(&Person::idNumber));
Where Compare is:
template<typename PointerToMemberData>
struct Compare {
Compare(PointerToMemberData pointerToMemberData) :
pointerToMemberData(pointerToMemberData) {
}
template<typename Type
bool operator()(Type lhs, Type rhs) {
return lhs.*pointerToMemberData < rhs.*pointerToMemberData
}
PointerToMemberData pointerToMemberData;
};