Click here to Skip to main content
15,885,435 members
Articles / Programming Languages / C++

Fast C++ Delegate: Boost.Function 'drop-in' replacement and multicast

Rate me:
Please Sign up or sign in to vote.
4.86/5 (51 votes)
1 Jun 200733 min read 291.5K   1.9K   110  
An article on the implementation of a fast C++ delegate with many advanced features.
#include <boost/config.hpp>

#if defined(BOOST_MSVC)
#pragma warning(disable: 4786)  // identifier truncated in debug info
#pragma warning(disable: 4710)  // function not inlined
#pragma warning(disable: 4711)  // function selected for automatic inline expansion
#pragma warning(disable: 4514)  // unreferenced inline removed
#endif

//
//  Test for fd::bind + __stdcall (member functions)
//  , modified from bind_stdcall_mf_test.cpp - test for bind.hpp + __stdcall (member functions)
//
//  Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//  Copyright (c) 2007 JaeWook Choi
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#define BOOST_MEM_FN_ENABLE_STDCALL

#include <boost/bind.hpp>

#define FD_MEM_FN_ENABLE_STDCALL

#include <fd/delegate/bind.hpp>

#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(push, 3)
#endif

#include <iostream>

#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(pop)
#endif

#include <boost/detail/lightweight_test.hpp>

struct X
{
    mutable unsigned int hash;

    X(): hash(0) {}

    int __stdcall f0() { f1(17); return 0; }
    int __stdcall g0() const { g1(17); return 0; }

    int __stdcall f1(int a1) { hash = (hash * 17041 + a1) % 32768; return 0; }
    int __stdcall g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; }

    int __stdcall f2(int a1, int a2) { f1(a1); f1(a2); return 0; }
    int __stdcall g2(int a1, int a2) const { g1(a1); g1(a2); return 0; }

    int __stdcall f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); return 0; }
    int __stdcall g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); return 0; }

    int __stdcall f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); return 0; }
    int __stdcall g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); return 0; }

    int __stdcall f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); return 0; }
    int __stdcall g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); return 0; }

    int __stdcall f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); return 0; }
    int __stdcall g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); return 0; }

    int __stdcall f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); return 0; }
    int __stdcall g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); return 0; }

    int __stdcall f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); return 0; }
    int __stdcall g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); return 0; }
};

void member_function_test()
{
    using boost::ref;
    using boost::bind;

    {
      X x;

      // 0

      bind(&X::f0, &x)();
      bind(&X::f0, ref(x))();

      bind(&X::g0, &x)();
      bind(&X::g0, x)();
      bind(&X::g0, ref(x))();

      // 1

      bind(&X::f1, &x, 1)();
      bind(&X::f1, ref(x), 1)();

      bind(&X::g1, &x, 1)();
      bind(&X::g1, x, 1)();
      bind(&X::g1, ref(x), 1)();

      // 2

      bind(&X::f2, &x, 1, 2)();
      bind(&X::f2, ref(x), 1, 2)();

      bind(&X::g2, &x, 1, 2)();
      bind(&X::g2, x, 1, 2)();
      bind(&X::g2, ref(x), 1, 2)();

      // 3

      bind(&X::f3, &x, 1, 2, 3)();
      bind(&X::f3, ref(x), 1, 2, 3)();

      bind(&X::g3, &x, 1, 2, 3)();
      bind(&X::g3, x, 1, 2, 3)();
      bind(&X::g3, ref(x), 1, 2, 3)();

      // 4

      bind(&X::f4, &x, 1, 2, 3, 4)();
      bind(&X::f4, ref(x), 1, 2, 3, 4)();

      bind(&X::g4, &x, 1, 2, 3, 4)();
      bind(&X::g4, x, 1, 2, 3, 4)();
      bind(&X::g4, ref(x), 1, 2, 3, 4)();

      // 5

      bind(&X::f5, &x, 1, 2, 3, 4, 5)();
      bind(&X::f5, ref(x), 1, 2, 3, 4, 5)();

      bind(&X::g5, &x, 1, 2, 3, 4, 5)();
      bind(&X::g5, x, 1, 2, 3, 4, 5)();
      bind(&X::g5, ref(x), 1, 2, 3, 4, 5)();

      // 6

      bind(&X::f6, &x, 1, 2, 3, 4, 5, 6)();
      bind(&X::f6, ref(x), 1, 2, 3, 4, 5, 6)();

      bind(&X::g6, &x, 1, 2, 3, 4, 5, 6)();
      bind(&X::g6, x, 1, 2, 3, 4, 5, 6)();
      bind(&X::g6, ref(x), 1, 2, 3, 4, 5, 6)();

      // 7

      bind(&X::f7, &x, 1, 2, 3, 4, 5, 6, 7)();
      bind(&X::f7, ref(x), 1, 2, 3, 4, 5, 6, 7)();

      bind(&X::g7, &x, 1, 2, 3, 4, 5, 6, 7)();
      bind(&X::g7, x, 1, 2, 3, 4, 5, 6, 7)();
      bind(&X::g7, ref(x), 1, 2, 3, 4, 5, 6, 7)();

      // 8

      bind(&X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
      bind(&X::f8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();

      bind(&X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
      bind(&X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8)();
      bind(&X::g8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();

      BOOST_TEST( x.hash == 23558 );
    }

    {
      X x;

      // 0

      fd::bind(&X::f0, &x )();
      fd::bind(&X::f0, ref(x))();

      fd::bind(&X::g0, &x)();
      fd::bind(&X::g0, x)();
      fd::bind(&X::g0, ref(x))();

      // 1

      fd::bind(&X::f1, &x)(1);
      fd::bind(&X::f1, ref(x))(1);

      fd::bind(&X::g1, &x)(1);
      fd::bind(&X::g1, x)(1);
      fd::bind(&X::g1, ref(x))(1);

      // 2

      fd::bind(&X::f2, &x)(1, 2);
      fd::bind(&X::f2, ref(x))(1, 2);

      fd::bind(&X::g2, &x)(1, 2);
      fd::bind(&X::g2, x)(1, 2);
      fd::bind(&X::g2, ref(x))(1, 2);

      // 3

      fd::bind(&X::f3, &x)(1, 2, 3);
      fd::bind(&X::f3, ref(x))(1, 2, 3);

      fd::bind(&X::g3, &x)(1, 2, 3);
      fd::bind(&X::g3, x)(1, 2, 3);
      fd::bind(&X::g3, ref(x))(1, 2, 3);

      // 4

      fd::bind(&X::f4, &x)(1, 2, 3, 4);
      fd::bind(&X::f4, ref(x))(1, 2, 3, 4);

      fd::bind(&X::g4, &x)(1, 2, 3, 4);
      fd::bind(&X::g4, x)(1, 2, 3, 4);
      fd::bind(&X::g4, ref(x))(1, 2, 3, 4);

      // 5

      fd::bind(&X::f5, &x)(1, 2, 3, 4, 5);
      fd::bind(&X::f5, ref(x))(1, 2, 3, 4, 5);

      fd::bind(&X::g5, &x)(1, 2, 3, 4, 5);
      fd::bind(&X::g5, x)(1, 2, 3, 4, 5);
      fd::bind(&X::g5, ref(x))(1, 2, 3, 4, 5);

      // 6

      fd::bind(&X::f6, &x)(1, 2, 3, 4, 5, 6);
      fd::bind(&X::f6, ref(x))(1, 2, 3, 4, 5, 6);

      fd::bind(&X::g6, &x)(1, 2, 3, 4, 5, 6);
      fd::bind(&X::g6, x)(1, 2, 3, 4, 5, 6);
      fd::bind(&X::g6, ref(x))(1, 2, 3, 4, 5, 6);

      // 7

      fd::bind(&X::f7, &x)(1, 2, 3, 4, 5, 6, 7);
      fd::bind(&X::f7, ref(x))(1, 2, 3, 4, 5, 6, 7);

      fd::bind(&X::g7, &x)(1, 2, 3, 4, 5, 6, 7);
      fd::bind(&X::g7, x)(1, 2, 3, 4, 5, 6, 7);
      fd::bind(&X::g7, ref(x))(1, 2, 3, 4, 5, 6, 7);

      // 8

      fd::bind(&X::f8, &x)(1, 2, 3, 4, 5, 6, 7, 8);
      fd::bind(&X::f8, ref(x))(1, 2, 3, 4, 5, 6, 7, 8);

      fd::bind(&X::g8, &x)(1, 2, 3, 4, 5, 6, 7, 8);
      fd::bind(&X::g8, x)(1, 2, 3, 4, 5, 6, 7, 8);
      fd::bind(&X::g8, ref(x))(1, 2, 3, 4, 5, 6, 7, 8);

      BOOST_TEST( x.hash == 23558 );
    }
}

int main()
{
    member_function_test();
    return boost::report_errors();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Other
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions