1

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);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
  • It's not compiling for me. code It's not compiling in c++11 either. Commented Aug 1, 2020 at 19:24
  • @cigien just checked, it is compiling for c++14, but not for newer version Commented Aug 1, 2020 at 19:25
  • which compiler are you using? Commented Aug 1, 2020 at 19:31
  • 1
    @idclev463035818 I am afraid i will not give a thrilling answer: whatever onlinegdb uses (onlinegdb.com) (could not find details). Commented Aug 1, 2020 at 19:36
  • I'm going to assume that this is a bug, since compilers don't allow it now (with the same language version). Commented Aug 1, 2020 at 19:36

1 Answer 1

4

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
Sign up to request clarification or add additional context in comments.

Comments

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.