Sam Daniel Sam Daniel - 2 months ago 7
C++ Question

The target set to std::function is lost

The target I set for std::function is lost, I don't know why perhaps I am overlooking some minor bug in this program. Can someone help.

class Test registers a lambda to a singleton class, but when tried to invoke the callback, the target set in std::function is lost.

#include <iostream>
#include <functional>

using namespace std;

class callback_store final
{

using callback_func_type = std::function<void()>;

public:
static callback_store instance()
{
static callback_store instance;
return instance;
}

void register_callback(callback_func_type func)
{
std::cout << "register_callback() <<<" << std::endl;
m_func = func;

// I am able to call the targets from here.
std::cout << "register_callback() func() " << std::endl;
func();
std::cout << "register_callback() m_func() " << std::endl;
m_func();

// some stats
std::cout << "register_callback() :: " << func.target_type().name() << std::endl;
}

void invoke_callback()
{
std::cout << "invoke_callback() <<< " << std::endl;

if (!m_func)
{
// This block is hit! Why
std::cout << "invoke_callback() :: m_func empty" << std::endl;
return;
}

return m_func();
}

private:
callback_func_type m_func;

};


class Test final
{
public:
Test()
{
callback_store::instance().register_callback([this](){do_test();});
}

~Test()
{
std::cout << "destructor" << std::endl;
}

private:
void do_test()
{
std::cout << "do_test() invoked !!" << std::endl;
}

};

int main()
{
cout << "Hello World" << endl;

Test t;

callback_store::instance().invoke_callback();


return 0;
}


Output:

sh-4.3$ g++ -std=c++11 -o main *.cpp
sh-4.3$ main
Hello World
register_callback() <<<
register_callback() func()
do_test() invoked !!
register_callback() m_func()
do_test() invoked !!
register_callback() :: ZN4TestC4EvEUlvE_
invoke_callback() <<<
invoke_callback() :: m_func empty
destructor

Answer

I think problem is the way you implemented your singleton class.

public:
static callback_store instance()
{
    static callback_store instance;
    return instance;
}

You are returning the copy of the of static object instead you should use

public:
static callback_store& instance()
{
    static callback_store instance;
    return instance;
}

And output of your code will be(tested):

Hello World
register_callback() <<<
register_callback() func() 
do_test() invoked !!
register_callback() m_func() 
do_test() invoked !!
register_callback() :: ZN4TestC4EvEUlvE_
invoke_callback() <<< 
do_test() invoked !!
destructor