Click here to Skip to main content
15,891,136 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 292.2K   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 + __cdecl (member functions)
//  , modified from  bind_cdecl_mf_test.cpp - test for bind.hpp + __cdecl (member functions)
//
//  Copyright (c) 2005 Peter Dimov
//  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_CDECL

#include <boost/bind.hpp>

#define FD_MEM_FN_ENABLE_CDECL

#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 __cdecl f0() { f1(17); return 0; }
    int __cdecl g0() const { g1(17); return 0; }

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

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

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

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

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

    int __cdecl f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); return 0; }
    int __cdecl 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 __cdecl 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 __cdecl 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 __cdecl 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 __cdecl 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