Click here to Skip to main content
15,891,843 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.3K   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

//
//  bind_eq_test.cpp - fd::bind equality comparison.
//  , modified from mem_fn_eq_test.cpp - boost::mem_fn equality operator
//
//  Copyright (c) 2004 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)
//

#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
{
    int dm_1;
    int dm_2;

    // 0

    int mf0_1() { return 0; }
    int mf0_2() { return 0; }

    int cmf0_1() const { return 0; }
    int cmf0_2() const { return 0; }

    void mf0v_1() {}
    void mf0v_2() {}

    void cmf0v_1() const {}
    void cmf0v_2() const {}

    // 1

    int mf1_1(int) { return 0; }
    int mf1_2(int) { return 0; }

    int cmf1_1(int) const { return 0; }
    int cmf1_2(int) const { return 0; }

    void mf1v_1(int) {}
    void mf1v_2(int) {}

    void cmf1v_1(int) const {}
    void cmf1v_2(int) const {}

    // 2

    int mf2_1(int, int) { return 0; }
    int mf2_2(int, int) { return 0; }

    int cmf2_1(int, int) const { return 0; }
    int cmf2_2(int, int) const { return 0; }

    void mf2v_1(int, int) {}
    void mf2v_2(int, int) {}

    void cmf2v_1(int, int) const {}
    void cmf2v_2(int, int) const {}

    // 3

    int mf3_1(int, int, int) { return 0; }
    int mf3_2(int, int, int) { return 0; }

    int cmf3_1(int, int, int) const { return 0; }
    int cmf3_2(int, int, int) const { return 0; }

    void mf3v_1(int, int, int) {}
    void mf3v_2(int, int, int) {}

    void cmf3v_1(int, int, int) const {}
    void cmf3v_2(int, int, int) const {}

    // 4

    int mf4_1(int, int, int, int) { return 0; }
    int mf4_2(int, int, int, int) { return 0; }

    int cmf4_1(int, int, int, int) const { return 0; }
    int cmf4_2(int, int, int, int) const { return 0; }

    void mf4v_1(int, int, int, int) {}
    void mf4v_2(int, int, int, int) {}

    void cmf4v_1(int, int, int, int) const {}
    void cmf4v_2(int, int, int, int) const {}

    // 5

    int mf5_1(int, int, int, int, int) { return 0; }
    int mf5_2(int, int, int, int, int) { return 0; }

    int cmf5_1(int, int, int, int, int) const { return 0; }
    int cmf5_2(int, int, int, int, int) const { return 0; }

    void mf5v_1(int, int, int, int, int) {}
    void mf5v_2(int, int, int, int, int) {}

    void cmf5v_1(int, int, int, int, int) const {}
    void cmf5v_2(int, int, int, int, int) const {}

    // 6

    int mf6_1(int, int, int, int, int, int) { return 0; }
    int mf6_2(int, int, int, int, int, int) { return 0; }

    int cmf6_1(int, int, int, int, int, int) const { return 0; }
    int cmf6_2(int, int, int, int, int, int) const { return 0; }

    void mf6v_1(int, int, int, int, int, int) {}
    void mf6v_2(int, int, int, int, int, int) {}

    void cmf6v_1(int, int, int, int, int, int) const {}
    void cmf6v_2(int, int, int, int, int, int) const {}

    // 7

    int mf7_1(int, int, int, int, int, int, int) { return 0; }
    int mf7_2(int, int, int, int, int, int, int) { return 0; }

    int cmf7_1(int, int, int, int, int, int, int) const { return 0; }
    int cmf7_2(int, int, int, int, int, int, int) const { return 0; }

    void mf7v_1(int, int, int, int, int, int, int) {}
    void mf7v_2(int, int, int, int, int, int, int) {}

    void cmf7v_1(int, int, int, int, int, int, int) const {}
    void cmf7v_2(int, int, int, int, int, int, int) const {}

    // 8

    int mf8_1(int, int, int, int, int, int, int, int) { return 0; }
    int mf8_2(int, int, int, int, int, int, int, int) { return 0; }

    int cmf8_1(int, int, int, int, int, int, int, int) const { return 0; }
    int cmf8_2(int, int, int, int, int, int, int, int) const { return 0; }

    void mf8v_1(int, int, int, int, int, int, int, int) {}
    void mf8v_2(int, int, int, int, int, int, int, int) {}

    void cmf8v_1(int, int, int, int, int, int, int, int) const {}
    void cmf8v_2(int, int, int, int, int, int, int, int) const {}

};


int main()
{
  // FD.Bind returns an instance of FD.Delegate which is not allowed to compare
  // equality directly using equality comparison operators in order to be coincident
  // with Boost.Function not able to do it. Instead uses equal_to() member function.
  {
    X x;
    X * px = &x;
    X const * cpx = &x;

    // 0

    BOOST_TEST(  fd::bind(&X::mf0_1, px).equal_to( fd::bind(&X::mf0_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf0_1, px).equal_to( fd::bind(&X::mf0_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf0_1, cpx).equal_to( fd::bind(&X::cmf0_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf0_1, cpx).equal_to( fd::bind(&X::cmf0_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf0v_1, px).equal_to( fd::bind(&X::mf0v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf0v_1, px).equal_to( fd::bind(&X::mf0v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf0v_1, cpx).equal_to( fd::bind(&X::cmf0v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf0v_1, cpx).equal_to( fd::bind(&X::cmf0v_2, cpx) ) );

    // 1

    BOOST_TEST(  fd::bind(&X::mf1_1, px).equal_to( fd::bind(&X::mf1_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf1_1, px).equal_to( fd::bind(&X::mf1_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf1_1, cpx).equal_to( fd::bind(&X::cmf1_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf1_1, cpx).equal_to( fd::bind(&X::cmf1_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf1v_1, px).equal_to( fd::bind(&X::mf1v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf1v_1, px).equal_to( fd::bind(&X::mf1v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf1v_1, cpx).equal_to( fd::bind(&X::cmf1v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf1v_1, cpx).equal_to( fd::bind(&X::cmf1v_2, cpx) ) );

    // 2
    BOOST_TEST(  fd::bind(&X::mf2_1, px).equal_to( fd::bind(&X::mf2_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf2_1, px).equal_to( fd::bind(&X::mf2_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf2_1, cpx).equal_to( fd::bind(&X::cmf2_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf2_1, cpx).equal_to( fd::bind(&X::cmf2_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf2v_1, px).equal_to( fd::bind(&X::mf2v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf2v_1, px).equal_to( fd::bind(&X::mf2v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf2v_1, cpx).equal_to( fd::bind(&X::cmf2v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf2v_1, cpx).equal_to( fd::bind(&X::cmf2v_2, cpx) ) );

    // 3

    BOOST_TEST(  fd::bind(&X::mf3_1, px).equal_to( fd::bind(&X::mf3_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf3_1, px).equal_to( fd::bind(&X::mf3_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf3_1, cpx).equal_to( fd::bind(&X::cmf3_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf3_1, cpx).equal_to( fd::bind(&X::cmf3_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf3v_1, px).equal_to( fd::bind(&X::mf3v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf3v_1, px).equal_to( fd::bind(&X::mf3v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf3v_1, cpx).equal_to( fd::bind(&X::cmf3v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf3v_1, cpx).equal_to( fd::bind(&X::cmf3v_2, cpx) ) );

    // 4

    BOOST_TEST(  fd::bind(&X::mf4_1, px).equal_to( fd::bind(&X::mf4_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf4_1, px).equal_to( fd::bind(&X::mf4_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf4_1, cpx).equal_to( fd::bind(&X::cmf4_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf4_1, cpx).equal_to( fd::bind(&X::cmf4_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf4v_1, px).equal_to( fd::bind(&X::mf4v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf4v_1, px).equal_to( fd::bind(&X::mf4v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf4v_1, cpx).equal_to( fd::bind(&X::cmf4v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf4v_1, cpx).equal_to( fd::bind(&X::cmf4v_2, cpx) ) );

    // 5

    BOOST_TEST(  fd::bind(&X::mf5_1, px).equal_to( fd::bind(&X::mf5_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf5_1, px).equal_to( fd::bind(&X::mf5_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf5_1, cpx).equal_to( fd::bind(&X::cmf5_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf5_1, cpx).equal_to( fd::bind(&X::cmf5_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf5v_1, px).equal_to( fd::bind(&X::mf5v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf5v_1, px).equal_to( fd::bind(&X::mf5v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf5v_1, cpx).equal_to( fd::bind(&X::cmf5v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf5v_1, cpx).equal_to( fd::bind(&X::cmf5v_2, cpx) ) );

    // 6

    BOOST_TEST(  fd::bind(&X::mf6_1, px).equal_to( fd::bind(&X::mf6_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf6_1, px).equal_to( fd::bind(&X::mf6_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf6_1, cpx).equal_to( fd::bind(&X::cmf6_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf6_1, cpx).equal_to( fd::bind(&X::cmf6_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf6v_1, px).equal_to( fd::bind(&X::mf6v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf6v_1, px).equal_to( fd::bind(&X::mf6v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf6v_1, cpx).equal_to( fd::bind(&X::cmf6v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf6v_1, cpx).equal_to( fd::bind(&X::cmf6v_2, cpx) ) );

    // 7

    BOOST_TEST(  fd::bind(&X::mf7_1, px).equal_to( fd::bind(&X::mf7_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf7_1, px).equal_to( fd::bind(&X::mf7_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf7_1, cpx).equal_to( fd::bind(&X::cmf7_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf7_1, cpx).equal_to( fd::bind(&X::cmf7_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf7v_1, px).equal_to( fd::bind(&X::mf7v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf7v_1, px).equal_to( fd::bind(&X::mf7v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf7v_1, cpx).equal_to( fd::bind(&X::cmf7v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf7v_1, cpx).equal_to( fd::bind(&X::cmf7v_2, cpx) ) );

    // 8

    BOOST_TEST(  fd::bind(&X::mf8_1, px).equal_to( fd::bind(&X::mf8_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf8_1, px).equal_to( fd::bind(&X::mf8_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf8_1, cpx).equal_to( fd::bind(&X::cmf8_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf8_1, cpx).equal_to( fd::bind(&X::cmf8_2, cpx) ) );

    BOOST_TEST(  fd::bind(&X::mf8v_1, px).equal_to( fd::bind(&X::mf8v_1, px) ) );
    BOOST_TEST( !fd::bind(&X::mf8v_1, px).equal_to( fd::bind(&X::mf8v_2, px) ) );

    BOOST_TEST(  fd::bind(&X::cmf8v_1, cpx).equal_to( fd::bind(&X::cmf8v_1, cpx) ) );
    BOOST_TEST( !fd::bind(&X::cmf8v_1, cpx).equal_to( fd::bind(&X::cmf8v_2, cpx) ) );
  }

  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