I have a class with a function
MyClass::doStuff(std::vector<MyCustomData*> toSort) { ...
in which I call
std::sort(toSort.begin(), toSort.end(), MyClass::SortByZ());
myClass::SortByZ() is a custom comparator.
Now this works but I would like to achieve the following:
I have several classes, which should each have its own comparator functor to sort "MyCustomData". So e.g. Class1... should have
class Class1 {
struct SortData {
bool operator ()(MyCustomData *lhs, MyCustomData *rhs) {
return lhs->something1 > rhs->something1;
}
};
//...many more functions/vars
}
while Class2 has a different comparator functor for the same datatype eg
class Class2 {
struct SortData {
bool operator ()(MyCustomData *lhs, MyCustomData *rhs) {
return lhs->something2 > rhs->something2;
}
};
//...many more functions/vars
}
Now I would like to be able to call the function MyClass::doStuff(...) with either
doStuff(myData, Class1::SortData)
or
doStuff(myData, Class2::SortData)
and the function MyClass::doStuff(...) should use the respective Sort-Order.
I did not find out a way of doing this, is there one? I would like a simple solution (doesn't have to support templates or anything). I would be willing to use boost if I needed that, but a solution without boost would be preferred.
I hope I was able to describe what I want to achieve? Thanks for any help!
You will have to make doStuff a template:
template <typename Comparator>
void doStuff(std::vector<MyCustomData*> toSort, Comparator compare) {
// ...
std::sort(toSort.begin(), toSort.end(), compare);
// ...
}
Also, it might want to take the first argument by reference. As it is, it will sort a copy of the argument, discard that copy, and leave the caller's vector untouched; although perhaps that's what you want.
Use a function template, in order to accept any kind of comparison function (or functor):
template <typename Comparator>
void doStuff(std::vector<MyCustomData> toSort, Comparator comparator)
{
...
std::sort(toSort.begin(), toSort.end(), comparator);
...
}
...
doStuff(myData, Class1::SortData());
doStuff(myData, Class2::SortData());
This is how standard algorithms provide genericity.
Related
I want to implement a container of generic types of element; and I want this container to support comparer.
When using STL's priority queue, I could define a comparer and initialise my priority queue container instance like this:
bool IsMyItemLarger(MyItem* a, MyItem* b) {
if(a && b && a->value > b->value)
return true;
return false;
}
std::priority_queue<
MyItem*,
vector<MyItem*>,
std::function<bool(MyItem*, MyItem*)>
> pq(IsMyItemLarger);
Now, I'd like to define my own container class, I'd like it to support any type including primitive type, so a template T should be in the class definition.
template<typename T...>
class MyContainer {
public:
vector<T*> items;
};
However, how can I define the comparer stub in my container class? (so that the client can pass e.g. "bool(MyItem*, MyItem*)" as a template argument and "IsMyItemLarger" as an argument of constructor?)
Note: (something off topic below!!)
I know how to implement SIMILAR class via interface, e.g.
I defined an interface and only items conforms to this interface can be insert into the container. It could pass compile (following code)
class AbstractBaseItem {
public:
virtual int compareTo(AbstractBaseItem* a) = 0;
};
class MyContainer {
public:
vector<AbstractBaseItem*> items;
bool greater(int i, int j) {
return items[i]->compareTo(items[j]) > 0;
}
};
class MyItem : public AbstractBaseItem {
public:
int value;
int compareTo(AbstractBaseItem* a) {
int aValue = ((MyItem*)a)->value;
if(value > aValue)
return 1;
else if(value < aValue)
return -1;
else
return 0;
}
};
However, logically, I don't want to use virtual functionality. All items in the container should be exactly the same type, not "as-is" type. E.g. I just want MyItem be in the container, not MyItem, YourItem, HisItem etc although these class all inherits from AbstractBaseItem. And it could be a primitive type like int, long, double...
So a template is actually what I wanted.
The comparison is delegated to another templated type, for convenience often left defaulted to std::greater<T> which does exactly what it seems to do; it's already available in the standard library, along with many other operations like less, greater_equal and so on, so no need to rewrite them. They're called operator wrappers and are available in
<functional>.
Therefore, have
template<typename T, typename Compare>
// ^^^^^^^^^^^^^^^^
class MyContainer {
vector<T*> items;
/* public: */Compare compare;
// ...
{
if ( compare(T1, T2) )
}
};
The signature for Compare must be
template <class T> bool cmp(const T&, const T&);
or similar in order to keep a standard design, where cmp(a, b) is expected to be a valid expression; of course, yours may different. More info about it here.
Containers generally allow you to use the comparator object they received, so you may want to make it public as well.
Tips, if I may:
Keep a vector<T>: pointers are bad; if you have to use them, prefer smart pointers.
You don't need std::function, just a callable object (plain functions, lambda ecc.)
I'm working on some code and I have a section where I do a one off sort function. To implement it I decided it was easiest to overload the operator< function. What I would prefer to do is move the implementation of the sort closer to the actual call by using some sort of boost::bind, boost::phoenix, lambda or some other type of implementation. Unfortunately I don't have access to new C++11 functionality. Below is some example code.
// In a header
struct foo
{
char * a;
char * c_str() { return a; }
}
// In a header
struct bar
{
foo * X;
bar(foo * _X) : X(_X) {}
bool operator < (const bar& rhs) const
{
return std::string(X->c_str()) < std::string(rhs.X->c_str());
}
};
struct bars : public std::vector<bar> { ... some stuff };
// Some other header
bars Bs;
// A cpp file
... other stuff happens that fills the Xs vector with objects
...::Function()
{
// Current use and it works fine
std::sort(Bs.begin(), Bs.end())
// Would like something that accomplishes this:
// std::sort(Bs.begin(), Bs.end(),
// std::string(lhs.X->c_str()) < std::string(rhs.X->c_str()))
// A non-working example of what I'm trying to do
// std::sort(Xs.begin(), Xs.end(),
// std::string((bind(bar::X->c_str(), _1)) <
// std::string((bind(bar::X->c_str(), _2)) )
}
I get lost when trying to figure out how to access the member pointers, member function and then cast the result all within a boost::bind function.
Thank you for your help.
I'm sure you can twist your way out of this using ample helpings of
Boost Phoenix bind and lambda
Boost Bind protect
However, I've learned to avoid these situations. Edit In fact, see below for one such contraption. I find this very very error prone and hard to reason about.
What you're seeing is, in essence, a violation of the Law Of Demeter. If you "just" wrote the code (not in a lambda), already it would be handling too many tasks.
So the first thing I'd do is rethink the class design.
The second thing I'd do is /extract/ different responsibilities from your comparator. Notice, that the comparator does three things:
access the c_str() of the X in lhs
access the c_str() of the X in rhs
compare the two
The first two steps are clear candidates for extraction. Let's write the generic comparer that remains first:
template <typename F>
struct compare_by_impl {
compare_by_impl(F f = F{}) : _f(std::move(f)) {}
template <typename T, typename U>
bool operator()(T const& a, U const& b) const {
return _f(a) < _f(b);
}
private:
F _f;
};
As always, it's nice to have factory function that will deduce the accessor type (in case you can get away with just using Phoenix there, it will save you specifying the (arcane) typenames involved in the expression templates):
template <typename Accessor>
compare_by_impl<Accessor> comparer_by(Accessor&& f) {
return compare_by_impl<Accessor>(std::forward<Accessor>(f));
}
Now you could already move the implementation with your sort call:
void Function()
{
struct accessX_c_str {
std::string operator()(bar const& b) const {
return b.X->c_str();
}
};
std::sort(Bs.begin(), Bs.end(), comparer_by(accessX_c_str()));
}
I'd personally leave it there.
Here's some more twisted contraptions:
// to avoid `comparer_by`
std::sort(Bs.begin(), Bs.end(), phx::bind(accessX_c_str(), arg1) < phx::bind(accessX_c_str(), arg2));
// to avoid any helper types (!?!?!? untested!)
std::sort(Bs.begin(), Bs.end(),
phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg1)))
< phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg2)))
);
I have a class which has a template:
template<class T = int> class slider;
The class has a void Process(void) method, so, I think it should be callable regarless of the type, return value is void and there are no parameters to it.
As for now I have this code to call process each frame in my application:
//class menu:
typedef boost::variant<std::shared_ptr<slider<int>>,std::shared_ptr<slider<float>>,std::shared_ptr<slider<double>>,std::shared_ptr<slider<char>>> slider_type;
std::map<std::string,slider_type> Sliders;
//buttons ... etc ...
void Process()
{
if(!Sliders.empty())
{
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
switch(i->second.which())
{
case 0://slider<int>
{
boost::get<std::shared_ptr<slider<int>>>(i->second)->Process();
break;
}
case 1://slider<float>
{
boost::get<std::shared_ptr<slider<float>>>(i->second)->Process();
break;
}
//.....
}
}
}
}
Is it possible to execute the functions Process() like in the following example?
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
switch(i->second.which())
{
boost::get<???Any???>(i->second)->Process();
}
}
If yes, how?
What would such a function return? You can't change the type of a function at runtime. And the point of a variant is that it's contents are determined at runtime.
The only thing it could return is a boost::any. Which is really just exchanging one kind of unknown for another (an unknown that's a lot harder to deal with when you don't know what it contains, mind you). But if you want to see such a visitor:
struct convert_to_any : public boost::static_visitor<boost::any>
{
template<typename T> boost::any operator() (const T& t) {return t;}
};
Use apply_visitor on that, and you will get an any back. Though I fail to see how that's helpful.
In any case, if you're using get on a variant, you are almost certainly doing the wrong thing. The correct way to access the elements of a variant is with a visitor, not with get.
In your case, the visitor should be simple:
struct ProcessVisitor : public boost::static_visitor<>
{
template<typename T> void operator() (const T& t) const {t->Process();}
};
Just use apply_visitor on that. If the variant contains a type that can be used with operator-> and the return value of that function can have Process called on it, then it will.
(Untested code!)
struct CallProcess : static_visitor<>
{
template <class T>
void operator()(const T &t) const
{
t->Process();
}
};
for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
{
boost::apply_visitor(CallProcess(), i->second);
}
No, not at all. You have to visit and deal with the case of every type. That is much better done with a visitor than your switch hack.
It's not possible because boost::variant has no way to know that all the types in the variant have anything in common. In fact, since the compiler generates a distinct class for each template specialization used, the address of the Process() function that would need to be used is different for each type in the boost::variant. To get around this you could abandon variant and use virtual functions and polymorphic classes sharing a common base class.
I have multiple controls organized like this:
deque<wxTextCtrl*> dequeEdit;
deque<wxStaticText*> dequeText;
deque<wxComboBox*> dequeCombo;
All these controls inherit from wxWindow which has mathod Show. I'd like to show (or hide) whole deque at once, without the need of multiple methods for each deque. How could it be done?
I was thinking about making deque of wxWindow for each control, so I could write method
ShowDeque(deque<wxWindow*> deque)
so showing would be easy, but on the other hand, if I'd like to work with e.g. combobox, I'd have to type it back to wxComboBox.
Are there any other possibilites? Thanks.
Use:
for_each(dequeEdit.begin(), dequeEdit.end(), mem_fun(&wxWindow::Show));
Same for any other deques.
Or encapsulate in one function:
template <class Deque>
void showAll(const Deque& dequeObj)
{
using namespace std;
for_each(dequeObj.begin(), dequeObj.end(), mem_fun(&wxWindow::Show));
}
showAll(dequeEdit);
std::for_each: http://en.cppreference.com/w/cpp/algorithm/for_each
std::mem_fun: http://en.cppreference.com/w/cpp/utility/functional/mem_fn
If it's a simple method make it a template:
template <typename WxT>
void ShowDeque(std::deque<WxT*> &d) { ... }
or better, use iterators to abstract out the container type:
template <typename WxIter>
void ShowDeque(WxIter begin, WxIter end) { ... }
or better yet use the standard facilities (Piotr beat me to that one while I was typing!)
You can use a function template.
template <typename T>
void show_all(const std::deque<T*>& d) {
for (typename std::deque<T*>::iterator it=d.begin(); it!=d.end(); ++it)
(*it)->Show();
}
You can then call it like a normal function.
deque<wxTextCtrl*> dequeEdit;
deque<wxStaticText*> dequeText;
deque<wxComboBox*> dequeCombo;
show_all(dequeEdit);
show_all(dequeText);
show_all(dequeCombo);
With a function template you can even make show_all independent of the container you use by adding an additional template argument.
template <typename C, typename T>
void show_all(const C<T*>& d) {
for (typename C<T*>::iterator it=d.begin(); it!=d.end(); ++it)
(*it)->Show();
}
C can then be any STL container, or even any container which supports the same iterator interface.
I came across this question when looking for how to use inheritance of iterators and deque.
The answer's does not give a complete answer related to inheritance, so I will add following:
Let say you have a class and you want this class to have the ability to have a deque inside, in other words to inherit the ability to control a deque container.
Example :
template<typename ElementType>
class myQueOfElements : public deque<ElementType>
{
ElementType placeholder;
myQueOfElements& operator=(unsigned char* rvalue)
{
unsigned char* ptrToNextElement = (unsigned char*)rvalue;
placeholder = ptrToNextElement; // make sure ElementType has its own assignment operator=
push_back(placeholder); // First element
//TODO: Iterate thru the binary and push_back the fetched elements
return *this;
}
};
// How to use:
myQueOfElements<myElementTypeClass> testQue;
testQue = (unsigned char*)&blob[0]; // address to binary data, will be parsed in the assignment operator=
// make sure it has same structure as the ElementType (myElementTypeClass)
// fetch all myElementTypeClass object(s) from the myQueOfElements
for (auto e : testQue) {
std::string strName = e.Name;
std::out << "Element : " << strName.c_str() << endl;
}
I've a templatized class
template <typename T>
class Factors
{
public:
Factors(){};
deque<string> stringsDeck;
// some methods and variables here
map <string, string> getNext();
};
The getNext method combines a string used as key with the strings from stringsDeck used as value and returns a map <string,string>.
Provided that I have templatized stringify and string2num functions, I would like to have a method map<string,Scalar> getNext() which for every other type except from string acts converting the values of the map to the specified template type T.
The compiler doesn't let me overload two methods with the same name but with different return type, specifically:
map <string, T > getNext()
{
// converts the values of getNext() return map into the specified type T
return convertedMapWithValuesOfTypeT;
}
What can be the solution in this case? I would like to keep the name of the method the same for string and other types (basically numerical types which can be converted from string via a lexical cast)
The language doesn't allow function overloads which differ only on
return type, because in most cases, the return type isn't considered in
function overload resolution. In this case, you really have three
possible solutions:
The simplest (and therefore the preferred solution in most cases) is
just to give the two functions different names:
getNextAsMapToType and
getNextAsMapToString, for example.
Alternatively, you could declare the function a template:
template<typename U>
std::map<string, U> getNext();
then, specialize this function for std::string and
T (and for
nothing else). The user will have to specify
getNext<std::string>()
or getNext<...> to call the one he wants.
Generally, I would find this considerably less readable than the
previous solution, but it might be applicable in templates, where
the names should contain or at least suggest the name of the type.
Finally, it _is_ possible to simulate overloading on the return
type, if you don't mind some extra complexity. To do this, you still
have to implement one of the other solutions, but the client code
doesn't see it. Basically, your getNext() function must return a
proxy, with overloaded conversion functions, something like:
class Proxy
{
Factors* myOwner;
public:
Proxy( Factors& owner ) : myOwner( &owner ) {}
operator std::map<std::string, std::string>() const
{
return myOwner->getNextAsMapToString();
}
operator std::map<std::string, T>() const
{
return myOwner->getNextAsMapToType();
}
};
Proxy getNext() { return Proxy( *this ); }
Client code can then just call getNext(), and depending on what they
do with the results, either getNextAsMapToString or
getNextAsMapToType will be called.
You can add a runtime-check in getNext using [typeid]
(http://en.cppreference.com/w/cpp/language/typeid) to see if T is a string or not.
Something like:
template <typename T>
class Factors
{
public:
Factors(){};
deque<string> stringsDeck;
// some methods and variables here
map <string, T> getNext();
{
if (typeid(T) == typeid(string))
{
// Special handling for strings
}
else
{
// Do something else for other types
}
}
};
Edit
As fschoenm suggests, template specialization is probably better:
template <typename T>
class Factors
{
public:
Factors(){};
// some methods and variables here
map <string, T> getNext();
};
template <>
class Factors<string>
{
public:
Factors(){};
deque<string> stringsDeck;
// some methods and variables here
map <string, string> getNext();
};