简体   繁体   中英

Function returning function pointer in C++11

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.

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
}

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 { ... }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM