Search code examples
c++c++11std-function

Is there something similar to std::function before C++11?


What construct should be used as surrogate for std::function<> when C++11 is not available ?
The alternative should basically allow to access private member functions of one class from another class like in the example below (other features of std::function are not used). Class Foo is fixed and can not be changed much, I have only access to class Bar.

class Foo {
  friend class Bar; // added by me, rest of the class is fixed
  private:

  void doStuffFooA(int i);
  void doStuffFooB(int i);
};

class Bar {
  public:

  Bar( Foo foo, std::function< void (const Foo&, int) > func ) {
    myFoo = foo;
    myFooFunc = func;
  };

  private:

  doStuffBar( const &Foo foo ) {
    myFooFunc( foo, 3 );
  }

  Foo myFoo;
  std::function< void (const Foo&, int) > myFooFunc;
}

int main() {

  Foo foo(...);

  Bar barA( foo, &Foo::doStuffFooA );

  Bar barB( foo, &Foo::doStuffFooB );
  ...
}

Solution

  • Is there something similar to std::function before C++11?

    Yes. There is Boost.Function (boost::function<>), which lately became part of the C++ Standard Library and provided a reference implementation for std::function<> ; similarly, Boost.Bind (boost::bind<>()) was adopted by the Standard and became std::bind<>().

    It implements a technique called type erasure for holding callable objects of any type. Here is a possible, illustrative implementation of how such a class template could be defined from scratch (do not use in production code, this is just an example):

    #include <memory>
    
    template<typename T>
    struct fxn { };
    
    template<typename R, typename... Args>
    struct fxn<R(Args...)>
    {
    
    public:
    
        template<typename F>
        fxn(F&& f) 
            : 
            _holder(new holder<typename std::decay<F>::type>(std::forward<F>(f)))
        { }
    
        R operator () (Args&&... args)
        { _holder->call(std::forward<Args>(args)...); }
    
    private:
    
        struct holder_base
        { virtual R call(Args&&... args) = 0; };
    
        template<typename F>
        struct holder : holder_base
        {
            holder(F&& f) : _f(std::forward<F>(f)) { }
            R call(Args&&... args) { return _f(std::forward<Args>(args)...); }
            F _f;
        };
    
        std::unique_ptr<holder_base> _holder;
    };
    
    #include <iostream>
    
    int main()
    {
        fxn<void()> f = [] { std::cout << "hello"; };
        f();
    }