1

I have the following C code :

inline void ChooseNext ( std::vector<RLS> & rls_vec_left_to_choose_,
           int & num_files_left_to_choose_, const int algo_,
           std::vector<RLS> & rls_vec_chosen_ )
{
if ( ( num_files_left_to_choose_ > 0 )
 && ( rls_vec_left_to_choose_.size ( ) > 0 ) )
  {
    switch ( algo_ )
      {
      case kAlgo1 :
        std::sort ( rls_vec_left_to_choose_.begin ( ), rls_vec_left_to_choose_.end ( ), SortFunc1 );
        break;
      case kAlgo2 :
      default:
        std::sort ( rls_vec_left_to_choose_.begin ( ), rls_vec_left_to_choose_.end ( ), SortFunc2 );
        break;
      }
      // etc
   }
 }

Where the sort functions are all of the type :

bool SortFunc1 ( const RLS & d1, const RLS & d2 ) ;

How do I change it to a function that takes const int algo_ and returns a bool (*) ( const RLS & d1, const RLS & d2 ) and then remove the switch case in this function ? I am trying to do it in as readable a manner as possible, and hopefully using C++11 features.

2
  • When you do that, I suspect you make it harder for the compiler to inline the function call of SortFuncX. This might impact your performance, so measure after changing it. Commented Dec 11, 2013 at 20:34
  • I just measured, it does have a measurable impact on performance, even in a small one-TU program. Sorting 10^7 32-bit integers takes about 10 % longer using function pointers on my VM, and 40 % longer using std::function when compared to the solution you currently have; using a g++4.8.1 and a clang++3.4 Commented Dec 11, 2013 at 20:56

2 Answers 2

3

If C++, why return a function pointer? You can use std::function instead:

std::function<bool(const RLS &, const RLS &)> ChooseNext(int algo)
{
    static const std::vector<std::function<bool(const RLS &, const RLS &)>> st {
        SortFunc1,
        SortFunc2,
        // etc.
    };

    return st[algo]; // assuming that `algo` goes from 0 to st.size()
}

If you really need a function pointer, then here's how you declare a function returning a function pointer:

bool (*ChooseNext())(const RLS &, const RLS &)
{
    // whatever
}
Sign up to request clarification or add additional context in comments.

2 Comments

Alternatively: auto ChooseNext(int algo) -> bool (*)(const RLS &, const RLS &). Might be easier to read.
@DyP That's nice, want to add it as an answer?
1

Although there is some advantage to using std::function<bool(RLS const&, RLS const&), it is interesting to create a function returing a function pointer. The easiest but also most boring approach is to use a typedef:

typedef bool (*CompareFunction)(RLS const&, RLS const&);
CompareFunciton getFunction(int algo) {
    switch (algo) {
    case kAlgo1: return &SortFunc1;
    case kAlgo2: return &SortFunc2;
    default: assert("algo selection value out of range");
    }
    return &SortFunc1; // ... or somehow deal with the situation
 }

OK, I'm not interested in dealing with the selection of the actual function but only with how the getFunction() is declared. There are obviously several ways how you can deal with algo being out of range (assert(), throw, use a default, ...). For the rest I'm not going to change the implementation but just the declaration.

What can be done with a typedef can also be done without! So, here is the C++03 version without using a typedef:

bool (*getFunction(int algo))(RLS const&, RLS const&) { ... }

OK, that looks plain weird but you can think of it as replacing the typedef with the actual function. To read what it does you need to read types right to left and inside out. No matter what, the above declaration is, mildly put, hideous. With C++11 it is possible to use trailing return types:

auto getFunction(int algo) -> bool(*)(RLS const&, RLS const&) { ... }

That notation is, I think, quite readable. Using a trailing return type for the function pointer can be done but doesn't necessarily improve readability, I think (but then, I may be just too old-school):

auto getFunction(int algo) -> auto (*)(RLS const&, RLS const&) -> bool { ... }

3 Comments

I think you have a typo in the last line - auto instead of -> auto.
@DyP: yes, that was a bit sloppy. I have fixed it. Thanks!
Thanks. I ended up with the auto -> bool(*) ... version. Seemed to be fastest. Didn't need a typedef as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.