#include <iostream>
#include <functional>
#include <memory>
#include <string>

using namespace std;

struct library
{
	library()
	{
		cout << "creating library\n";
	}
	~library()
	{
		cout << "destroying library\n";
	}
};

template<typename Signature>
class library_function
{
public:
    library_function(
        shared_ptr<library> lib, Signature* library_function)
        :
    m_library(lib),
    m_function(library_function)
   {}
   
    operator Signature*() const { return m_function; }

private:
   shared_ptr<library> m_library;
   Signature* m_function;
};
 
void test_lib_func(string s)
{
	cout << "called test_lib_func(" << s << ")\n";
}

int main()
{
	shared_ptr<library> lib = make_shared<library>();
	{
	    library_function<void(string)> functor(lib, test_lib_func);
	    functor("direct call before reset");
	    lib.reset();
	    functor("direct call after reset");
	    cout << "functor about to go out of scope\n";
	}
	
	lib = make_shared<library>();
	function<void(string)> func =
	    library_function<void(string)>(lib, test_lib_func);
	func("std::function call before reset");
	lib.reset();
	func("std::function call after reset");
	return 0;
}