4

I've got this class:

template <class T>
class list
{
    ...
    bool moreThan(T x, T y);
    bool lessThan(T x, T y);
    ...
};

I need a function pointer to change the behavior of my class, and switch between using bool moreThan(T, T) or bool lessThan(T, T). So I'm currently using:

bool (list<int>::*foo)(int x, int y);
foo = &list<int>::lessThan;

and to use it:

(this->*foo)(x, y);

but I would like to have a flexible function pointer, so that I can use it with whichever T I need, not just int. So is there a way to create a function pointer to a class template member? Something like:

template <class T>
bool (list<T>::*foo)(T x, T y); //this doesn't work
Michael
  • 1,018
  • 4
  • 14
  • 30

3 Answers3

2

No there isn't. A pointer-to-member has to point to something. A member function in a class template isn't a single function, it's a family of functions - and each one has a different type. There could even be a T for which list<T>::lessThan doesn't exist, or is a type or a variable!

If we made an alias for one such pointer to member:

template <typename T>
using CompFun = bool (list<T>::*)(T, T);

Then it's obvious that CompFun<int> and CompFun<string> are different types. You cannot create a generic CompFun<T> variable.

Depending on what it is you're trying to do, though, there might be a good way to accomplish that.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • I really wish you'd stop using this ambiguous term "method". – Lightness Races in Orbit Apr 18 '15 at 03:08
  • 2
    @LightningRacisinObrit What's ambiguous about it? – Barry Apr 18 '15 at 03:10
  • 2
    The term 'method' is not well-defined in C++. Did you mean to imply a function that is a member? Or one that is non-static? Or one that is virtual? Or one that is pure? To avoid misunderstandings, prefer _standardized_ terminology: instead of `method' say 'function' prefixed with those specifiers that are relevant. We're not doing Java here. – Lightness Races in Orbit Apr 18 '15 at 03:21
  • 1
    @LightningRacisinObrit I take it you're not a fan of [this question](http://stackoverflow.com/q/155609/2069064)? Sure, "method" isn't a term in C++, but it's a term in OO. I use it to just mean function that is a member of a class (whether static/virtual/pure or not). – Barry Apr 18 '15 at 03:29
  • thanks, just one question: Do I need to declare the function pointer with ``list::`` to know that it's pointing to a function of the class ``list`` right? but why does it need to know? – Michael Apr 18 '15 at 03:32
  • Question is tagged [tag:c++], not [tag:oo]. – Lightness Races in Orbit Apr 18 '15 at 04:29
2

Currently you have to do something like this:

template <typename T>
struct listComparePtr
{
    typedef bool (list<T>::*type)(T x, T y);
};

Use like this:

listComparePtr<int>::type foo = &list<int>::lessThan;
listComparePtr<double>::type foo2 = &list<double>::moreThan;
Steve
  • 1,760
  • 10
  • 18
0

There's no such single function pointer, because a function pointer must point to a concrete address in memory, but each template instance will be a different function in a different place.

However, your attempt at a declaration is already a valid C++14 variable template. Example: http://coliru.stacked-crooked.com/a/b1f0904e0ee4d6ad

Similarly, you can put the templating into a C++14 generic lambda:

auto foo = []( auto && l, auto && x, auto && y )
             { return l.moreThan( x, y ); };

This has the advantage of giving you a handle which is a single type, although the function inside the lambda is still a template.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421