Problem with function pointer in class method

Hi there. I'm trying to sort a vector with a custom sort method. I cannot seem to figure out the correct syntax to use std::sort() with the third parameter, since I am trying to do this within class methods, and not my main.cpp file.

Edit: here's the error I'm getting:
error: must use '.*' or '->*' to call pointer-to-member function

Here's what I have:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "SpreadSheet.h"

bool SpreadSheet::sortMethod(Sortable* a, Sortable* b)
{
    return a->value() > b->value();
}

void SpreadSheet::sortLinesBy(std::string categoryName)
{
    //m_categories[categoryName] returns an std::vector<Sortable*>
    std::vector<Sortable*> newVector = m_categories[categoryName];
    std::sort(newVector.begin(), newVector.end(), sortSortablesMethod);
}


I have learned through my exploration of the internet that I am dealing with function pointers. I don't quite understand the examples people have posted, but all of them seem to be a bit different than mine anyway.

Does anyone know how I can fix this?
Last edited on
What is sortSortablesMethod?

There's two simple solutions:
1. Make the sort predicate a free function.
2. Make the sort predicate a static member function.
3. Use std::bind() or std::function() to create a closure over the class context.
4. Just put the sorting predicate in a lambda, inline. Judging by the sorting code, this would work:
1
2
3
4
std::sort(newVector.begin(), newVector.end(),
          [] (Sortable *a, Sortable *b) { 
            return a->value() > b->value(); 
          });


Some other potential issues:
The signature of SpreadSheet::sortMethod implies that it modifies the Sortable objects it accesses. That's not allowed, so perhaps change the signature to accept Sortable const *const instead. You might have to mark Sortable::value() const as well.

Why are you storing pointers in a vector? That puts the burden of memory access on you. Store the values by default; if that's not acceptable, consider std::reference_wrapper or preferably a smart pointer that reflects the ownership semantics you want. (Probably you want std::unique_ptr, if this class Sortable is polymorphic?)

Note: (this is why the sort() invocation doesn't compile)
Function pointers are one thing.
Non-static member function pointers require context to invoke - their environment - an associated instance of the class.

This makes sense, because in order to call a member function at any point, you have to have a class instance to operate upon:
my_instance.do_stuff(args);

When you're trying to call a member function through a member-function pointer, you need a class instance on the left, and special syntax in-between. Here's an example.
1
2
3
4
/* The following line creates a member-function pointer to SpreadSheet::sortMethod. */
/* But which SpreadSheet specifically?  We don't know yet. */
bool (&SpreadSheet::*sort_fn)(Sortable*, Sortable*) = &SpreadSheet::sortMethod;
my_spreadsheet_instance.*sort_fn(a, b);


std::sort assumes that it recieves some sort of normal function or functor (i.e., not a member function) but since it's a template you'll get a compile error inside std::sort() as the result of complete substitution failure.
Last edited on
mbozzi,

Thank you very much for the robust response. What you say makes a lot of sense, and I'm not sure why it didn't occur to me to just make the function static. In any case, your code snippet seems like by far the easiest way to do it, so I will give that a shot.

I probably won't get to try this stuff until tomorrow, but thank you for a bunch of ways to look at the problem.

This is the sort of thing (specific, advanced syntax) that reminds me I'm still but a wee baby programmer. I had never even heard of function pointers in my 3 years of programming.

Thank you!!
Just an update:

All I had to do was make the function static and it solved everything. Thanks again!
Topic archived. No new replies allowed.