Function that returns a pointer to another function

Can any kind fellow explain me fp11() and fp03 functions step by step? The resource I have been learning C++ from does not mention such language construct. And how is fp1000 different than the those two? Follow up question: for what reasons should one avoid using std::function?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <string>
#include <functional>


void f0(const std::string& arg = " function. (default arg)") {
  std::cout << "\"" << __PRETTY_FUNCTION__ << "\"" << arg << '\n';
}

auto fp11() -> void (*)(const std::string&) {
  return f0;
}

void (*fp03())(const std::string&) {
  return f0;
}

std::function<void(const std::string&)> fp1000() {
  return f0;
}

int main() {
  f0();
  fp1000()(" <== function.");
  fp11()(" <== function.");
  fp03()(" <== function.");
}
Can any kind fellow explain me fp11() and fp03 functions step by step?

Trying to guess:
fp11() it’s a normal function defined by the new “trailing return type syntax”
Cfr ‘auto 2)’ here:
http://en.cppreference.com/w/cpp/language/auto
2) In a function declaration that uses the trailing return type syntax, the keyword auto does not perform automatic type detection. It only serves as a part of the syntax.


You could rewrite it as (*fp03()) at row 10.
Both means: I’m a function which returns a pointer to a function which takes an argument std::string and returns nothing.

The resource I have been learning C++ from does not mention such language construct.

It’s new since C++11. It’s (shortly) described here:
http://en.cppreference.com/w/cpp/language/function
trailing(C++11) - Trailing return type, useful if the return type depends on argument names, such as
template <class T, class U> auto add(T t, U u) -> decltype(t + u);
or is complicated, such as in
auto fpif(int)->int(*)(int)


And how is fp1000 different than the those two?

fp1000() is a function which takes no arguments and returns an object of type std::function<void(const std::string&)>
You can find information on std::function here:
http://en.cppreference.com/w/cpp/utility/functional/function

Follow up question: for what reasons should one avoid using std::function?

In my opinion the most obscure syntax in your code is the ‘traditional’ one, the one could apply also to C. I mean the one of (*fp03()).
I think std::function is a better alternative, so I can’t see any downside in it, expecially if you are comparing it to a pointer to function. IMHO.
When writing code like this
 
void (*fp03())(const std::string&)

Use type aliases!
Edit: see @Enoziat's post below:
1
2
using my_function = void(std::string const&);
my_function* fp03()

Rarely you encounter declarations like this where type aliases aren't used. There's a trick to reading these declarations, sometimes called the "right-left rule".
http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html
There's also cdecl (a website and command-line tool) that can help if you're doubting yourself.
https://cdecl.org/

Follow up question: for what reasons should one avoid using std::function?

There is overhead. Type erasure implies some at runtime, and the inclusion of thousands of lines of dense template code in <functional> can slow down compilation. Sometimes you hear it should be avoided, but this is IMO a simple restatement of Ya Ain't Gonna Need It: avoid complicated abstractions & extra functionality unless it will simplify the problem.
Last edited on
I’ve seen this post is already marked solved, but the problem is I tried the following code and it didn’t compile:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>
#include <functional>


void f0(const std::string& arg = " function. (default arg)") {
  std::cout << "\"" << __PRETTY_FUNCTION__ << "\"" << arg << '\n';
}

auto fp11() -> void (*)(const std::string&) {
  return f0;
}

using my_function = void(std::string const&);
my_function fp03()
{
  return f0;
}

std::function<void(const std::string&)> fp1000() {
  return f0;
}

int main() {
  f0();
  fp1000()(" <== function.");
  fp11()(" <== function.");
  fp03()(" <== function.");
}

15:18: error: 'fp03' declared as function returning a function
 my_function fp03()
                  ^


I managed to compile it changing
using my_function = void(std::string const&);
this way:
using my_function = void(*)(std::string const&);
@Enoziat, thanks for catching that! I've fixed it above.

The alias will work as a parameter, but not as a return type, because a function type F is silently replaced with F* if it appears in a parameter list (and very similar rules apply to arrays):
1
2
3
4
5
6
7
using my_function = void(std::string const&);
void foo(my_function pfn); // fine
my_function* bar(); // also fine

using my_function_ptr = void(*)(std::string const&);
void foo2(my_function_ptr pfn); // fine
my_function_ptr bar2(); // also fine 

I tend to write function aliases that way because it's easier to read.

Arguably.
Last edited on
mbozzi wrote:
Sometimes you hear it should be avoided, but this is IMO a simple restatement of Ya Ain't Gonna Need It: avoid complicated abstractions & extra functionality unless it will simplify the problem.
. . .
I tend to write function aliases that way because it's easier to read.
Arguably.

I’ve just learnt new things, thanks to you. But, may I ask you to bear with my poor English and clarify me if you prefer, in general, std::function or pointers to function? I’m totally ignorant on this topic and I’ll be glad to know your opinion.

(And, if you want to make your post perfect, perhaps there’s an URL to fix: “ http://https://cdecl.org/ ”)

@aedt, I hope it isn’t a problem for you if I briefly hijack this thread.
> in general, std::function or pointers to function?

In general, neither. Strongly favour the abstraction of a callable object.

For example:
1
2
3
4
5
6
7
8
9
10
namespace std
{ 
    class thread 
    {
        // ...
        template< typename FUNCTION, typename... ARGS > 
        explicit thread( FUNCTION&& fn, ARGS&&... args );
        // ...
    }
}


Re. std::function or pointers to function?
There is an obvious quality of implementation issue in how efficient a call through std::function<> is.
In practice calling a function through the call wrapper (std::function<>) is quite inexpensive.

foo.cpp
1
2
3
4
5
6
7
#include <functional>

int foo( int a ) { return a/2 + a%3 ; }

std::function< int(int) > wrapped_foo() { return foo ; }

std::function< int(int) > wrapped_closure() { return [] ( int a ) { return a/2 + a%3 ; }; }

http://coliru.stacked-crooked.com/a/6b675cad4fe8463b

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <ctime>
#include <functional>
#include <algorithm>
#include <numeric>

int foo( int a ) ;
std::function< int(int) > wrapped_foo() ;
std::function< int(int) > wrapped_closure() ;

template < std::size_t N > int bar( const int (&srce)[N], int (&dest)[N], const std::function< int(int) >& fn )
{
    const auto start = std::clock() ;
    std::transform( srce, srce+N, dest, fn ) ;
    return ( std::clock() - start ) * 1000.0 / CLOCKS_PER_SEC ;
}

int main()
{
    constexpr std::size_t N = 1024*1024*32 ;
    static int srce[N] {};
    static int dest[N] {};
    std::iota( srce, srce+N, 0 ) ;
    std::iota( dest, dest+N, 0 ) ; // to get equivalent cache locality for all cases

    std::cout << "    raw function pointer: " <<  bar( srce, dest, &foo ) << " millisecs\n" ;
    std::cout << "wrapped function pointer: " <<  bar( srce, dest, wrapped_foo() ) << " millisecs\n" ;
    std::cout << " wrapped closure (local): " <<  bar( srce, dest, []( int a ) { return a/2 + a%3 ; } ) << " millisecs\n" ;
    std::cout << "wrapped closure (extern): " <<  bar( srce, dest, wrapped_closure() ) << " millisecs\n" ;
    std::cout << "------------------------------------------------\n" ;
    std::cout << "    raw function pointer: " <<  bar( srce, dest, &foo ) << " millisecs\n" ;
    std::cout << "wrapped function pointer: " <<  bar( srce, dest, wrapped_foo() ) << " millisecs\n" ;
    std::cout << " wrapped closure (local): " <<  bar( srce, dest, []( int a ) { return a/2 + a%3 ; } ) << " millisecs\n" ;
    std::cout << "wrapped closure (extern): " <<  bar( srce, dest, wrapped_closure() ) << " millisecs\n" ;
}

http://coliru.stacked-crooked.com/a/6b4553c0283db4c9

Typical result (clang++/libc++, -O3):
    raw function pointer: 162 millisecs
wrapped function pointer: 162 millisecs
 wrapped closure (local): 150 millisecs
wrapped closure (extern): 153 millisecs


What is expensive with std::function<> is the cost of construction of the call wrapper, in comparison to the zero-cost of obtaining a pointer to a function.

The standard call wrapper provides an enormous amount of flexibility. Between the two, in general favour call wrappers over raw pointers to functions, unless callable objects must be constructed and destroyed with alarming frequency, and performance is (measured to be) a concern.
Last edited on
Your code is really hard form me to understand, JLBorges. I think it must have taken you quite a long time to write such a painstaking explanation form me and the other users of this forum, so thank you very much indeed.
I had made a silly mistake in writing the test function; it should have been:
1
2
// template < std::size_t N > int bar( const int (&srce)[N], int (&dest)[N], const std::function< int(int) >& fn )
template < std::size_t N, typename FN > int bar( const int (&srce)[N], int (&dest)[N], const FN& fn )

or the call would be through the wrapper even for the raw pointer to function.

With the corrected code, the results are more along expected lines:

    raw function pointer: 118 millisecs
wrapped function pointer: 173 millisecs
         closure (local): 78 millisecs
wrapped closure (extern): 166 millisecs

http://coliru.stacked-crooked.com/a/b72687b8506bb3e5

A local closure is faster than anything else; and calling with a raw function pointer is faster than calling through a call wrapper. But the difference is not much:
The local closure is faster than the wrapped call by about 0.0031 nanoseconds per call;
raw pointer to pointer is faster than the wrapped call by about 0.0017 nanoseconds per call.
Topic archived. No new replies allowed.