The following code compiled:
#include <iostream>
#include <functional>
typedef void (*f_type) (int a);
void say(int a)
{
std::cout << a << "!" << std::endl;
}
int main()
{
int a=5;
say(a);
std::function<void(int)> fn{say};
f_type fn_pointer = fn.target<void(int)>();
if(fn_pointer)
fn_pointer(a);
else
std::cout << "null ptr" << std::endl;
return 0;
}
but when executed prints:
5!
nullptr
I would like to understand why target returned an empty ptr, and not a pointer to the function "say".
note : it compiles for c++ up to c++14, for c++17 onward, compilation fails with error (which is cryptic to me):
In file included from /usr/include/c++/7/functional:58:0,
from main.cpp:11:
/usr/include/c++/7/bits/std_function.h: In instantiation of ‘_Functor* std::function<_Res(_ArgTypes ...)>::target() [with _Functor = void(int); _Res = void; _ArgTypes = {int}]’:
<span class="error_line" onclick="ide.gotoLine('main.cpp',28)">main.cpp:28:46</span>: required from here
/usr/include/c++/7/bits/std_function.h:733:9: error: invalid use of const_cast with type ‘void (*)(int)’, which is a pointer or reference to a function type
return const_cast<_Functor*>(__func);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reproduced it on VS2017, seems like the target
method returns a pointer to pointer (as in returning a pointer to the actual function pointer stored in the object), and expecting its template type argument accordingly. Here is a modified example that works:
#include <iostream>
#include <functional>
typedef void(*f_type) (int a);
void say(int a)
{
std::cout << a << "!" << std::endl;
}
int main()
{
int a = 5;
say(a);
std::function<void(int)> fn{say};
f_type* fn_pointer = fn.target<void(*)(int)>();
if (fn_pointer)
(*fn_pointer)(a);
else
std::cout << "null ptr" << std::endl;
return 0;
}
Confirmed target
returning a pointer to the actual function pointer by running the following:
#include <iostream>
#include <functional>
typedef void(*f_type) (int a);
void say(int a)
{
std::cout << a << "!" << std::endl;
}
void say_boo(int a)
{
std::cout << "booooo" << std::endl;
}
int main()
{
int a = 5;
std::function<void(int)> fn{say};
f_type* fn_pointer = fn.target<void(*)(int)>();
(*fn_pointer)(a);
fn = say_boo;
(*fn_pointer)(a);
return 0;
}
This produced the following output:
5!
booooo