Type signature of comparison function object - c++

How can I use a comparison function object type in a method signature? Eg., this is all fine:
struct compInt {
bool operator() (const int a, const int b) { return a < b; }
};
set<int,compInt> s1;
// Actually this is no good, but removing it would obfuscate
// the accepted answer:
set<int> s2(compInt);
[The last one compiles but it's a function declaration, s2 turns out not to be a container].
But I want to do this:
void func (____ x)
{
set<int> s(x);
}
I do not want to do this:
template<typename C>
void func (C& c)
{
set<int> s(c);
}
And function<bool(const int,const int)> does not work. I tried making compInt::operator() virtual so I could do this:
void func (compInt& ci)
And pass in derived objects, but in fact set<int> s(ci) then fails to compile (which I'm almost grateful for, because it is a horrid hack).

set<int> s1(compInt);
This declares a function whose return type is set<int>.
set<int> s(x);
This declares a local variable of type set<int>. The comparator type is not deduced from the argument, but instead the default template argument is used. As such, compInt is not used as the comparator, so you cannot pass an instance of compInt to the constructor.
You can use:
void func (compInt x)
{
std::set<int,compInt> s(x);
I tried making compInt::operator() virtual so I could do this:
void func (compInt& ci)
Polymorphic comparator would be quite problematic. Set stores the object by value, so passing into the function through a reference would not help. You would need to use type erasure: Define a wrapper comparator that takes a polymorphic comparator as constructor argument, stores it in dynamic storage, and delegates the call operator to the stored polymorphic comparator. Then use the wrapper type as the template argument of the set.

Eeroiki got me going in the right direction. What I eventually settled on was this (note the objects to be compared actually aren't ints, and a wide range of comparators could be applied to them).
using intCompFunc = std::function<bool(const int,const int)>
struct compInt {
intCompFunc comp;
bool operator() (const int a, const int b) const {
return comp(a, b);
}
void foo (intCompfunc icf)
{
compInt ci { icf };
std::set<int,compInt> s1(ci);
}
Which means the user can pass in any kind of functor, eg. a lambda:
foo([] (const int a, const int b) { return a < b; });
My confusion stems from why it isn't this way in the first place, which I think is really a historical problem (there were no C++11 functors when the STL was written). OTOH, using a base type instead of a template parameter does introduce some runtime overhead.

Related

C++: How to sort a vector of objects derived from class using one of its parameters

I'm trying to sort a vector of objects, created from a class in the project.
I have two classes - Playlist and ListIndex, that inherits from a List_base class. In the List_base class, I want to sort a vector of objects (either Playlist or ListIndex) by their name. the name property is defined in the List_base class. I tried using struct or function that compares the name field and pass it to the sort function. I'm getting all kinds of errors. I'm new to C++ and stuck in this error for a very long time
The List_base sort method with the compare function
//the function should be able to get either Playlist vector
// or ListIndex vector (both inherits from List_base)
void List_base::sortList(vector<List_base> data) {
sort(data.begin(), data.end(), compFunc());
}
bool List_base::compFunc(List_base *a, List_base *b) {
return a->getName().compare(b->getName()) > 0;
}
The name field is declared in the List_base class:
class List_base
{
public:
List_base(string name);
string getName();
void sortList(vector<List_base> data);
virtual ~List_base();
protected:
private:
string name;
bool compFunc(List_base *a, List_base *b);
};
What am I doing wrong? I can't even focus on a specific error.
I've also tried casting but failed there too
pls, help!
std::sort expects the comparator you pass to be some callable type, whether that's a function pointer, functor, lambda, etc. It just needs something that can be called with a signature like bool compare(const T& left, const T& right).
The first problem is that passing compFunc() is calling the function compFunc. This should fail because compFunc expects two arguments. You should pass the function itself, not its return value:
sort(data.begin(), data.end(), compFunc);
The second problem is that in your compare function you should accept the arguments by reference-to-const, not by pointer:
bool compFunc(const List_base& a, const List_base& b);
where List_base is exactly the element type you're sorting.
The third problem is that compFunc is a non-static member function. This means that this function depends on a List_base instance to be used, and you need a secret this parameter to call it, as in this->compFunc(...). You should instead make it static or non-member, so that it can be treated as a normal function.
class List_base {
/* ... */
static bool compFunc(const List_base& a, const List_base& b);
};
bool List_base::compFunc(const List_base& a, const List_base& b){
return a.name < b.name;
}
Your sorting should work at this point. If you want to use the sorted result outside of List_base::sortList, you should accept data by reference, so that the changes you make can be seen by the caller. Currently, sortList accepts the list by value, meaning that it always receives a copy of what you pass it.
Perhaps the cleanest fix to all this would be to the "less-than" operator (<), which the standard library uses by default in many cases to compare user-defined types. This could like something like the following:
class List_base {
/* ... */
friend bool operator<(const List_base& a, const List_base& b){
return a.name < b.name;
}
};
with this, you don't need to explicitly specify your own comparator, and sorting is now as simple as
sort(data.begin(), data.end());

Where is thee callback happening in this code?

class Add
{
Add(){cout<<"ctor";}
void operator()(int a ,int b){return a+b;}
}
int main()
{
Add(3,4);
}
Add is the functor.And functor can help in callback mechanism right? So where is it happening here??
And functor can help in callback mechanism right?
Yes. You could write a function template that uses a functor to perform a user-defined operation as part of whatever it's doing; for example:
template <typename Fn>
void do_stuff(Fn f, int a, int b) {
int c = f(a, b);
do_something(c);
}
and then inject your operation thusly:
do_stuff(Add(), 3, 4);
One specific use is the std::sort algorithm, which can use a user-supplied functor to compare types that don't support normal comparison operators.
So where is it happening here??
It isn't; your code doesn't compile. After fixing the return value (since it returns a value not void), you could create and invoke a function with
Add()(3,4);
But that's not particularly useful.

Functors - how can I use them with typedef?

This is a functor:
class add_x {
int x;
public:
add_x(int x) : x(x) {}
int operator()(int y) { return x + y; }
};
And from main I can do this:
add_x add10(10); // create my functor
int i = add10(20); // add 20 and return it
How can I combine the functor with typedef?
For instance, I came across this:
typedef int (*myfuncType)(float f, char c1,char c2);
myfuncType pt2Function = NULL;
But what am I defining here exactly? operator ()?
Function pointer is - as its name says - just a pointer to function. You cannot use a pointer to function to point to functor, which is essentially a class with overloaded () operator.
You may be interested in std::function from C++11:
#include <functional>
(...)
std::function<int(int)> fn = add_x(10);
int i = fn(20);
Edit: Ok, I see, what you are asking for.
Maybe some code will make things clear.
int fn(float a, char b, char c) { ... }
(...)
typedef int (*myFuncType)(float f, char c1, char c2);
myFuncType ptrToFun = &fn;
(*fn)(1.0f, 'a', 'z');
This typedef creates a "pointer-to-function" type. If you declare a variable of this type, then you'll be able to assign to it a pointer to function (extracted with regular & operator) and - for example - pass to another function or just store (or call this function).
std::function is a lot more flexible, because you can store in it a pointer to function, a functor or even a lambda and call them normally.
I don't understand your first question (How can I combine the functor with typedef ?), so I can't answer that - a typedef would work as it would with any other class.
Regarding your second question: the line
typedef int (*myfuncType)(float f, char c1,char c2);
gives a name (myfunctType) to the type int (*)(float, char, char) (read: "a function which takes a float and two char values and then returns an int").
So
myfuncType pt2Function = NULL;
Defines a variable which can point to such an above-mentioned function, but sets the pointer to NULL for now.
Here, myfuncTypeis a type describing a pointer of function, with three float parameters and which return an int. A functor is just a class with operator() overload. So the typedef is used just like other class.
typedef add_x add will work.

What is the effect of `const` modifier and reference in the template argument of std::function

I am not sure about the effect of const modifier and reference in the template argument of std::function. For example, in the following codes, should I use std::function<bool(std::string, std::string)> or std::function<bool(const std::string&, const std::string&)> as the base class ? I tested both in GCC 4.4, however, there was no difference. Thanks in advance.
#include <iostream>
#include <functional>
#include <string>
//struct FLess : public std::function<bool(std::string, std::string)>
struct FLess : public std::function<bool(const std::string&, const std::string&)>
{
bool operator () (const std::string& s1, const std::string& s2) const
{
return s1 < s2;
}
};
int main(int argc, char* argv[])
{
FLess f;
std::string a = "a";
std::string b = "b";
std::cerr << f(a, b) << std::endl;
return 0;
}
You are not supposed to inherit from std::function.
Rather you use to abstract the underlying kind of function object like this:
void DoSomething(function<void(const string&, const string&) myF)
{
string s1, s2;
myF(s1, s2);
}
// usage:
DoSomething(bind(otheFunc, ....));
DoSomething([](const string& s1, const string& s2) { ... });
struct Func
{
operator()(const string& s1, const string& s2)
{ ... }
}
Func f;
DoSomething(f);
Now to answer your question, if you use const string& you are asking the compiler not to copy the object and to forbid modifications. That choice depends on the meaning you are giving to your parameters.
For small types like numbers and small struct, pass by copy.
Unless you want to perform very advanced copy/move optimizations, you'd better always use const& for large types. I'd consider string a large type, unless you are sure that it will never grow.
It boils down to compatibility between the function object's parameter types and those of the callable entity it is referring to, if the function's parameter types can be converted to the callable entities parameter types or not:
void foo(double x, double y);
void bar(const double& x, const double& y);
void fooBar(double& x, double& y);
std::function<void(const double&, const double&)> f;
f = &foo; // OK
f = &bar; // OK
f = &fooBar; // Error on GCC 4.7. Cannot instantiate a double& from const double.
Interestingly, an std::function with void return type is compatible with callable entities with any return type:
int fooBarFoo(const double& x, const double& y);
f = &fooBarFoo; // OK
So in your case, where you are comparing passing by const reference as opposed to passing by value, I think there is no observable difference.
Passing a reference to a const object avoids making a copy of the object just to pass to the function. In your case (a tiny string) it probably doesn't make enough difference to notice.
If you were dealing with a string of (say) several megabytes, passing by reference to const would avoid allocating space for (and copying) all that data.
At the same time, most compilers internally implement references pretty much like pointers. This can lead to slower execution because of an extra level of indirection. For small items (char, int, probably long) you usually prefer to pass by value. For larger items (potentially long strings, matrices, etc.) you usually prefer to pass by reference. If in doubt, usually pass by reference -- the penalty for being wrong in this direction is generally fairly small.

When are stateless class functors useful in place of a c style function?

I've found some good examples of functors on SO like this one, and all the convincing examples seem to use state in the class that defines operator().
I came across an example in a book that defines the function call operator without having state, and I can't help but feel like this is an awkward usage, and that a normal style function pointer, would be better than using operator() in every way here - less code, less variables (you have to instantiate the comparators), its probably more efficient due to the instantiation, and no loss of meaning or encapsulation (since it's just one function).
I know std::sort lets you pick between operator() classes and functions, but I've always just used the functions because of the above logic.
What are the reasons why a class might be preferred?
Here's the example (paraphrased):
class Point2D {
//.. accessors, constructors
int x,y;
};
class HorizComp {
public:
bool operator()(const Point2D& p, const Point2D& q) const
{ return p.getX() < q.getX(); }
};
class VertComp {
public:
bool operator()(const Point2D& p, const Point2D& q) const
{ return p.getY() < q.getY(); }
};
template <typename E, typename C>
void printSmaller(const E& p, const E& q, const C& isLess) {
cout << (isLess(p, q) ? p : q) << endl; // print the smaller of p and q
}
//...
// usage in some function:
Point2D p(1.2, 3.2), q(1.5, 9.2);
HorizComp horizComp;
VertComp vorizComp;
printSmaller(p, q, horizComp);
printSmaller(p, q, vorizComp);
The typical reason is that when you do this:
bool less_than(const Point&, const Point&);
// ...
std::sort(..., &less_than);
The template argument for the predicate is the following:
bool(const Point&,const Point&)
Since the sort function receives a function pointer, it is more difficult for the compiler to inline the predicate use inside std::sort(). This happens because you could have another function
bool greater_than(const Point&, const Point&);
which has the exact same type, meaning the std::sort() instatiation would be shared between the two predicates. (remember that I said that it makes inlining more difficult, not impossible).
In contrast, when you do this:
struct less_than {
bool operator()(const Point&, const Point&) const;
};
// ...
std::sort(..., less_than());
struct greater_than {
bool operator()(const Point&, const Point&) const;
};
// ...
std::sort(..., greater_than());
The compiler generates a unique template instantiation for std::sort() for each predicate, making it easier to inline the predicate's definition.
One reason is run-time efficiency. If you pass a pointer to a function, the compiler has to be unusually clever to produce code for that function inline. Passing an object that defines operator() makes it much easier for the compiler to produce the code inline. Especially for something like sorting, this can increase speed quite substantially.
In C++11, another reason to use a class is for convenience -- you can use a lambda expression to define the class.
Others have made good points about the ability for the compiler to inline the functor. One other possibile advantage of functor objects vs. function pointers is flexibility. The functor might be a template, maybe a derived class, perhaps it has run time configuration (even if stateless at the time operator() is called etc.
Another reason is that sometimes one comparison function is not enough. Let's say we have a vector of pointers:
struct X { string name; };
vector<shared_ptr<X>> v;
Now if we want to sort the vector by name, we have to define our own predicate for the sort function:
struct Cmp1
{
bool operator()(const shared_ptr<X>& left, const shared_ptr<X>& right) const
{ return left->name < right->name; }
};
That's cool, but what do we do when we need to find the objects with specific name? To work with equal_range, the predicate needs to have two different comparison functions:
struct Cmp2
{
bool operator()(const shared_ptr<X>& left, const string& right) const
{ return left->name < right; }
bool operator()(const string& left, const shared_ptr<X>& right) const
{ return left < right->name; }
};
This allows us to call equal_range with a string name object:
equal_range(v.begin(), v.end(), name, Cmp2())
In template libraries where the state of functor argument is not known at definition time, argument of class type provides a more generic interface than none-instance function pointers.
STL is a great example where the statefull or stateless perdicates and functors can be used as parameters to classes and functions.
If template programming is not part of the plan, function pointer is superior to stateless functor class; a single instance of function can accept all function pointers of a specific signature and code size is minimized. But in case there is a minimal probability of future library extension, functor makes it more generic.