1
0
forked from boostorg/bind

__fastcall support added.

[SVN r14465]
This commit is contained in:
Peter Dimov
2002-07-15 14:07:03 +00:00
parent 5b1528f3f4
commit 35ee2f3a52
7 changed files with 590 additions and 32 deletions

View File

@@ -46,7 +46,7 @@
<h4 style="MARGIN-LEFT: 40pt"><a href="#Q_mac">Does <b>bind</b> work with Mac toolbox <h4 style="MARGIN-LEFT: 40pt"><a href="#Q_mac">Does <b>bind</b> work with Mac toolbox
functions?</a></h4> functions?</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#Q_extern_C">Does <b>bind</b> work with extern <h4 style="MARGIN-LEFT: 40pt"><a href="#Q_extern_C">Does <b>bind</b> work with extern
&quot;C&quot; functions?</a></h4> "C" functions?</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#Q_auto_stdcall">Why doesn't <b>bind</b> automatically <h4 style="MARGIN-LEFT: 40pt"><a href="#Q_auto_stdcall">Why doesn't <b>bind</b> automatically
recognize nonstandard functions?</a></h4> recognize nonstandard functions?</a></h4>
<h3 style="MARGIN-LEFT: 20pt"><a href="#Troubleshooting">Troubleshooting</a></h3> <h3 style="MARGIN-LEFT: 20pt"><a href="#Troubleshooting">Troubleshooting</a></h3>
@@ -77,7 +77,8 @@
<h4 style="MARGIN-LEFT: 40pt"><a href="#Files">Files</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#Files">Files</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#Dependencies">Dependencies</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#Dependencies">Dependencies</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#NumberOfArguments">Number of Arguments</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#NumberOfArguments">Number of Arguments</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#stdcall">"__stdcall" and "pascal" Support</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#stdcall">"__stdcall", "__fastcall",&nbsp;and
"pascal" Support</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#BOOST_BIND">Using the BOOST_BIND macro</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#BOOST_BIND">Using the BOOST_BIND macro</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#visit_each"><b>visit_each</b> support</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#visit_each"><b>visit_each</b> support</a></h4>
<h3 style="MARGIN-LEFT: 20pt"><a href="#Acknowledgements">Acknowledgements</a></h3> <h3 style="MARGIN-LEFT: 20pt"><a href="#Acknowledgements">Acknowledgements</a></h3>
@@ -455,13 +456,13 @@ template&lt;class T&gt; void f(T const &amp; t);
alternative is to treat the function as a <a href="#with_function_objects">generic alternative is to treat the function as a <a href="#with_function_objects">generic
function object</a> and use the bind&lt;R&gt;(f, ...) syntax. function object</a> and use the bind&lt;R&gt;(f, ...) syntax.
</p> </p>
<h3><a name="Q_extern_C">Does <b>bind</b> work with extern &quot;C&quot; functions?</a></h3> <h3><a name="Q_extern_C">Does <b>bind</b> work with extern "C" functions?</a></h3>
<p> <p>
Sometimes. On some platforms, pointers to extern &quot;C&quot; functions are Sometimes. On some platforms, pointers to extern "C" functions are equivalent
equivalent to &quot;ordinary&quot; function pointers, so they work fine. Other to "ordinary" function pointers, so they work fine. Other platforms treat them
platforms treat them as different types. A platform-specific implementation of <b>bind</b> as different types. A platform-specific implementation of <b>bind</b> is
is expected to handle the problem transparently; this implementation does not. expected to handle the problem transparently; this implementation does not. As
As usual, the workaround is to treat the function as a <a href="#with_function_objects"> usual, the workaround is to treat the function as a <a href="#with_function_objects">
generic function object</a> and use the bind&lt;R&gt;(f, ...) syntax. generic function object</a> and use the bind&lt;R&gt;(f, ...) syntax.
</p> </p>
<h3><a name="Q_auto_stdcall">Why doesn't <b>bind</b> automatically recognize <h3><a name="Q_auto_stdcall">Why doesn't <b>bind</b> automatically recognize
@@ -471,8 +472,9 @@ template&lt;class T&gt; void f(T const &amp; t);
lock-in. Had the <a href="#stdcall">appropriate macros</a> been defined lock-in. Had the <a href="#stdcall">appropriate macros</a> been defined
automatically, you could have accidentally taken advantage of them without automatically, you could have accidentally taken advantage of them without
realizing that your code is, perhaps, no longer portable. In addition, some realizing that your code is, perhaps, no longer portable. In addition, some
compilers have the option to make <b>__stdcall</b> their default calling compilers have the option to make <b>__stdcall</b> (<STRONG>__fastcall</STRONG>)
convention, in which case no separate support would be necessary. their default calling convention, in which case no separate support would be
necessary.
</p> </p>
<h2><a name="Troubleshooting">Troubleshooting</a></h2> <h2><a name="Troubleshooting">Troubleshooting</a></h2>
<h3><a name="err_num_args">Incorrect number of arguments</a></h3> <h3><a name="err_num_args">Incorrect number of arguments</a></h3>
@@ -589,7 +591,7 @@ int main()
a2, ..., aN) <A href="#Q_forms">form</A> works with nonstandard functions. a2, ..., aN) <A href="#Q_forms">form</A> works with nonstandard functions.
</p> </p>
<p> <p>
On some platforms, extern &quot;C&quot; functions, like <b>std::strcmp</b>, are not On some platforms, extern "C" functions, like <b>std::strcmp</b>, are not
recognized by the short form of bind. recognized by the short form of bind.
</p> </p>
<P> <P>
@@ -753,8 +755,8 @@ namespace
<b>Effects:</b> Equivalent to <tt>bind&lt;typename F::result_type, F&gt;(f);</tt> <b>Effects:</b> Equivalent to <tt>bind&lt;typename F::result_type, F&gt;(f);</tt>
</p> </p>
<p> <p>
<b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> <b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> via
via other means as an extension, without relying on the <tt>result_type</tt> member. other means as an extension, without relying on the <tt>result_type</tt> member.
</p> </p>
</blockquote> </blockquote>
<h4><a name="bind_2">template&lt;class R&gt; <i>unspecified-2</i> bind(R (*f) ())</a></h4> <h4><a name="bind_2">template&lt;class R&gt; <i>unspecified-2</i> bind(R (*f) ())</a></h4>
@@ -789,8 +791,8 @@ namespace
a1);</tt> a1);</tt>
</p> </p>
<p> <p>
<b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> <b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> via
via other means as an extension, without relying on the <tt>result_type</tt> member. other means as an extension, without relying on the <tt>result_type</tt> member.
</p> </p>
</blockquote> </blockquote>
<h4><a name="bind_4">template&lt;class R, class B1, class A1&gt; <i>unspecified-4</i> bind(R <h4><a name="bind_4">template&lt;class R, class B1, class A1&gt; <i>unspecified-4</i> bind(R
@@ -822,8 +824,8 @@ namespace
a1);</tt> a1);</tt>
</p> </p>
</blockquote> </blockquote>
<h4><a name="bind_6_1">template&lt;class R, class T, class A1&gt; <i>unspecified-6-1</i> bind(R <h4><a name="bind_6_1">template&lt;class R, class T, class A1&gt; <i>unspecified-6-1</i>
T::*f, A1 a1)</a></h4> bind(R T::*f, A1 a1)</a></h4>
<blockquote> <blockquote>
<p> <p>
<b>Effects:</b> Equivalent to <tt>bind&lt;R const &amp;&gt;(<a href="mem_fn.html">boost::mem_fn</a>(f), <b>Effects:</b> Equivalent to <tt>bind&lt;R const &amp;&gt;(<a href="mem_fn.html">boost::mem_fn</a>(f),
@@ -852,8 +854,8 @@ namespace
a1, a2);</tt> a1, a2);</tt>
</p> </p>
<p> <p>
<b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> <b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> via
via other means as an extension, without relying on the <tt>result_type</tt> member. other means as an extension, without relying on the <tt>result_type</tt> member.
</p> </p>
</blockquote> </blockquote>
<h4><a name="bind_8">template&lt;class R, class B1, class B2, class A1, class A2&gt; <i>unspecified-8</i> <h4><a name="bind_8">template&lt;class R, class B1, class B2, class A1, class A2&gt; <i>unspecified-8</i>
@@ -888,8 +890,8 @@ namespace
</blockquote> </blockquote>
<h3><a name="AdditionalOverloads">Additional overloads</a></h3> <h3><a name="AdditionalOverloads">Additional overloads</a></h3>
<p> <p>
Implementations are allowed to provide additional <b>bind</b> overloads in order to Implementations are allowed to provide additional <b>bind</b> overloads in
support more arguments or different function pointer variations. order to support more arguments or different function pointer variations.
</p> </p>
<h2><a name="Implementation">Implementation</a></h2> <h2><a name="Implementation">Implementation</a></h2>
<h3><a name="Files">Files</a></h3> <h3><a name="Files">Files</a></h3>
@@ -951,7 +953,7 @@ namespace
This implementation supports function objects with up to nine arguments. This This implementation supports function objects with up to nine arguments. This
is an implementation detail, not an inherent limitation of the design. is an implementation detail, not an inherent limitation of the design.
</p> </p>
<h3><a name="stdcall">"__stdcall" and "pascal" Support</a></h3> <h3><a name="stdcall">"__stdcall", "__fastcall", and "pascal" Support</a></h3>
<p> <p>
Some platforms allow several types of (member) functions that differ by their <b>calling Some platforms allow several types of (member) functions that differ by their <b>calling
convention</b> (the rules by which the function is invoked: how are convention</b> (the rules by which the function is invoked: how are
@@ -960,8 +962,8 @@ namespace
</p> </p>
<p> <p>
For example, Windows API functions and COM interface member functions use a For example, Windows API functions and COM interface member functions use a
calling convention known as <b>__stdcall</b>. Mac toolbox functions use a <b>pascal</b> calling convention known as <b>__stdcall</b>.Borland VCL components use <STRONG>__fastcall</STRONG>.
calling convention. Mac toolbox functions use a <b>pascal</b> calling convention.
</p> </p>
<p> <p>
To use <b>bind</b> with <b>__stdcall</b> functions, <b>#define</b> the macro <b>BOOST_BIND_ENABLE_STDCALL</b> To use <b>bind</b> with <b>__stdcall</b> functions, <b>#define</b> the macro <b>BOOST_BIND_ENABLE_STDCALL</b>
@@ -971,10 +973,16 @@ namespace
To use <b>bind</b> with <b>__stdcall</b> <b>member</b> functions, <b>#define</b> To use <b>bind</b> with <b>__stdcall</b> <b>member</b> functions, <b>#define</b>
the macro <b>BOOST_MEM_FN_ENABLE_STDCALL</b> before including <b>&lt;boost/bind.hpp&gt;</b>. the macro <b>BOOST_MEM_FN_ENABLE_STDCALL</b> before including <b>&lt;boost/bind.hpp&gt;</b>.
</p> </p>
<p> <P>To use <B>bind</B> with <B>__fastcall</B> functions, <B>#define</B> the macro <B>BOOST_BIND_ENABLE_FASTCALL</B>
before including <B>&lt;boost/bind.hpp&gt;</B>.
</P>
<P>To use <B>bind</B> with <B>__fastcall</B> <B>member</B> functions, <B>#define</B>
the macro <B>BOOST_MEM_FN_ENABLE_FASTCALL</B> before including <B>&lt;boost/bind.hpp&gt;</B>.
</P>
<P>
To use <b>bind</b> with <b>pascal</b> functions, <b>#define</b> the macro <b>BOOST_BIND_ENABLE_PASCAL</b> To use <b>bind</b> with <b>pascal</b> functions, <b>#define</b> the macro <b>BOOST_BIND_ENABLE_PASCAL</b>
before including <b>&lt;boost/bind.hpp&gt;</b>. before including <b>&lt;boost/bind.hpp&gt;</b>.
</p> </P>
<p> <p>
[Note: this is a non-portable extension. It is not part of the interface.] [Note: this is a non-portable extension. It is not part of the interface.]
</p> </p>

165
bind_fastcall_mf_test.cpp Normal file
View File

@@ -0,0 +1,165 @@
#if defined(_MSC_VER) && !defined(__ICL)
#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_stdcall_mf_test.cpp - test for bind.hpp + __stdcall (member functions)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#define BOOST_MEM_FN_ENABLE_FASTCALL
#include <boost/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
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
struct X
{
mutable unsigned int hash;
X(): hash(0) {}
void __fastcall f0() { f1(17); }
void __fastcall g0() const { g1(17); }
void __fastcall f1(int a1) { hash = (hash * 17041 + a1) % 32768; }
void __fastcall g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; }
void __fastcall f2(int a1, int a2) { f1(a1); f1(a2); }
void __fastcall g2(int a1, int a2) const { g1(a1); g1(a2); }
void __fastcall f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); }
void __fastcall g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); }
void __fastcall f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); }
void __fastcall g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); }
void __fastcall f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); }
void __fastcall g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); }
void __fastcall f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); }
void __fastcall g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); }
void __fastcall f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); }
void __fastcall 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); }
void __fastcall 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); }
void __fastcall 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); }
};
void member_function_test()
{
using namespace boost;
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 );
}
int test_main(int, char * [])
{
member_function_test();
return 0;
}

110
bind_fastcall_test.cpp Normal file
View File

@@ -0,0 +1,110 @@
#if defined(_MSC_VER) && !defined(__ICL)
#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_fastcall_test.cpp - test for bind.hpp + __fastcall (free functions)
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#define BOOST_BIND_ENABLE_FASTCALL
#include <boost/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
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
//
long __fastcall f_0()
{
return 17041L;
}
long __fastcall f_1(long a)
{
return a;
}
long __fastcall f_2(long a, long b)
{
return a + 10 * b;
}
long __fastcall f_3(long a, long b, long c)
{
return a + 10 * b + 100 * c;
}
long __fastcall f_4(long a, long b, long c, long d)
{
return a + 10 * b + 100 * c + 1000 * d;
}
long __fastcall f_5(long a, long b, long c, long d, long e)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e;
}
long __fastcall f_6(long a, long b, long c, long d, long e, long f)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f;
}
long __fastcall f_7(long a, long b, long c, long d, long e, long f, long g)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g;
}
long __fastcall f_8(long a, long b, long c, long d, long e, long f, long g, long h)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h;
}
long __fastcall f_9(long a, long b, long c, long d, long e, long f, long g, long h, long i)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h + 100000000 * i;
}
void function_test()
{
using namespace boost;
int const i = 1;
BOOST_TEST( bind(f_0)(i) == 17041L );
BOOST_TEST( bind(f_1, _1)(i) == 1L );
BOOST_TEST( bind(f_2, _1, 2)(i) == 21L );
BOOST_TEST( bind(f_3, _1, 2, 3)(i) == 321L );
BOOST_TEST( bind(f_4, _1, 2, 3, 4)(i) == 4321L );
BOOST_TEST( bind(f_5, _1, 2, 3, 4, 5)(i) == 54321L );
BOOST_TEST( bind(f_6, _1, 2, 3, 4, 5, 6)(i) == 654321L );
BOOST_TEST( bind(f_7, _1, 2, 3, 4, 5, 6, 7)(i) == 7654321L );
BOOST_TEST( bind(f_8, _1, 2, 3, 4, 5, 6, 7, 8)(i) == 87654321L );
BOOST_TEST( bind(f_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i) == 987654321L );
}
int test_main(int, char * [])
{
function_test();
return 0;
}

View File

@@ -1343,6 +1343,18 @@ template<class F, class A1, class A2, class A3, class A4, class A5, class A6, cl
#endif #endif
#ifdef BOOST_BIND_ENABLE_FASTCALL
#define BOOST_BIND_CC __fastcall
#define BOOST_BIND_ST
#include <boost/bind/bind_cc.hpp>
#undef BOOST_BIND_CC
#undef BOOST_BIND_ST
#endif
#ifdef BOOST_BIND_ENABLE_PASCAL #ifdef BOOST_BIND_ENABLE_PASCAL
#define BOOST_BIND_ST pascal #define BOOST_BIND_ST pascal
@@ -1377,6 +1389,18 @@ template<class F, class A1, class A2, class A3, class A4, class A5, class A6, cl
#endif #endif
#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
#define BOOST_BIND_MF_NAME(X) X##_fastcall
#define BOOST_BIND_MF_CC __fastcall
#include <boost/bind/bind_mf_cc.hpp>
#undef BOOST_BIND_MF_NAME
#undef BOOST_BIND_MF_CC
#endif
// data member pointers // data member pointers
template<class R, class T, class A1> template<class R, class T, class A1>

View File

@@ -66,6 +66,18 @@ template<class V> struct mf
#endif #endif
#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
#define BOOST_MEM_FN_NAME(X) inner_##X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
#include <boost/bind/mem_fn_template.hpp>
#undef BOOST_MEM_FN_CC
#undef BOOST_MEM_FN_NAME
#endif
#undef BOOST_MEM_FN_RETURN #undef BOOST_MEM_FN_RETURN
}; // struct mf<V> }; // struct mf<V>
@@ -95,6 +107,18 @@ template<> struct mf<void>
#endif #endif
#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
#define BOOST_MEM_FN_NAME(X) inner_##X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
#include <boost/bind/mem_fn_template.hpp>
#undef BOOST_MEM_FN_CC
#undef BOOST_MEM_FN_NAME
#endif
#undef BOOST_MEM_FN_RETURN #undef BOOST_MEM_FN_RETURN
}; // struct mf<void> }; // struct mf<void>
@@ -126,6 +150,20 @@ template<> struct mf<void>
#endif #endif
#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
#define BOOST_MEM_FN_NAME(X) X##_fastcall
#define BOOST_MEM_FN_NAME2(X) inner_##X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
#include <boost/bind/mem_fn_vw.hpp>
#undef BOOST_MEM_FN_NAME
#undef BOOST_MEM_FN_NAME2
#undef BOOST_MEM_FN_CC
#endif
} // namespace _mfi } // namespace _mfi
#else // #ifdef BOOST_NO_VOID_RETURNS #else // #ifdef BOOST_NO_VOID_RETURNS
@@ -158,6 +196,18 @@ namespace _mfi
#endif #endif
#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
#define BOOST_MEM_FN_NAME(X) X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
#include <boost/bind/mem_fn_template.hpp>
#undef BOOST_MEM_FN_CC
#undef BOOST_MEM_FN_NAME
#endif
#undef BOOST_MEM_FN_RETURN #undef BOOST_MEM_FN_RETURN
} // namespace _mfi } // namespace _mfi
@@ -187,6 +237,18 @@ namespace _mfi
#endif #endif
#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
#define BOOST_MEM_FN_NAME(X) X##_fastcall
#define BOOST_MEM_FN_CC __fastcall
#include <boost/bind/mem_fn_cc.hpp>
#undef BOOST_MEM_FN_NAME
#undef BOOST_MEM_FN_CC
#endif
// data member support // data member support
namespace _mfi namespace _mfi

View File

@@ -37,7 +37,8 @@
<h4 style="MARGIN-LEFT: 40pt"><a href="#Files">Files</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#Files">Files</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#Dependencies">Dependencies</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#Dependencies">Dependencies</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#NumberOfArguments">Number of Arguments</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#NumberOfArguments">Number of Arguments</a></h4>
<h4 style="MARGIN-LEFT: 40pt"><a href="#stdcall">"__stdcall" Support</a></h4> <h4 style="MARGIN-LEFT: 40pt"><a href="#stdcall">"__stdcall" and
"__fastcall"&nbsp;Support</a></h4>
<h3 style="MARGIN-LEFT: 20pt"><a href="#Acknowledgements">Acknowledgements</a></h3> <h3 style="MARGIN-LEFT: 20pt"><a href="#Acknowledgements">Acknowledgements</a></h3>
<h2><a name="Purpose">Purpose</a></h2> <h2><a name="Purpose">Purpose</a></h2>
<p> <p>
@@ -321,7 +322,7 @@ template&lt;class R, class T, class A1, class A2&gt; <i>implementation-defined-6
This implementation supports member functions with up to eight arguments. This This implementation supports member functions with up to eight arguments. This
is not an inherent limitation of the design, but an implementation detail. is not an inherent limitation of the design, but an implementation detail.
</p> </p>
<h3><a name="stdcall">"__stdcall" Support</a></h3> <h3><a name="stdcall">"__stdcall" and "__fastcall" Support</a></h3>
<p> <p>
Some platforms allow several types of member functions that differ by their <b>calling Some platforms allow several types of member functions that differ by their <b>calling
convention</b> (the rules by which the function is invoked: how are convention</b> (the rules by which the function is invoked: how are
@@ -330,16 +331,19 @@ template&lt;class R, class T, class A1, class A2&gt; <i>implementation-defined-6
</p> </p>
<p> <p>
For example, Windows API functions and COM interface member functions use a For example, Windows API functions and COM interface member functions use a
calling convention known as <b>__stdcall</b>. calling convention known as <b>__stdcall</b>. Borland VCL components use <STRONG>__fastcall</STRONG>.
</p> </p>
<p> <p>
To use <b>mem_fn</b> with <b>__stdcall</b> member functions, <b>#define</b> the To use <b>mem_fn</b> with <b>__stdcall</b> member functions, <b>#define</b> the
macro <b>BOOST_MEM_FN_ENABLE_STDCALL</b> before including, directly or macro <b>BOOST_MEM_FN_ENABLE_STDCALL</b> before including, directly or
indirectly, <b>&lt;boost/mem_fn.hpp&gt;</b>. indirectly, <b>&lt;boost/mem_fn.hpp&gt;</b>.
</p> </p>
<p> <P>To use <B>mem_fn</B> with <B>__fastcall</B> member functions, <B>#define</B> the
[Note: this is a non-portable extension. It is not part of the interface.] macro <B>BOOST_MEM_FN_ENABLE_FASTCALL</B> before including, directly or
</p> indirectly, <B>&lt;boost/mem_fn.hpp&gt;</B>.
</P>
<P>[Note: this is a non-portable extension. It is not part of the interface.]
</P>
<p> <p>
[Note: Some compilers provide only minimal support for the <b>__stdcall</b> keyword.] [Note: Some compilers provide only minimal support for the <b>__stdcall</b> keyword.]
</p> </p>

185
mem_fn_fastcall_test.cpp Normal file
View File

@@ -0,0 +1,185 @@
#if defined(_MSC_VER) && !defined(__ICL)
#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
//
// mem_fn_fastcall_test.cpp - a test for mem_fn.hpp + __fastcall
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#define BOOST_MEM_FN_ENABLE_FASTCALL
#include <boost/mem_fn.hpp>
#include <boost/shared_ptr.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
struct X
{
mutable unsigned int hash;
X(): hash(0) {}
void __fastcall f0() { f1(17); }
void __fastcall g0() const { g1(17); }
void __fastcall f1(int a1) { hash = (hash * 17041 + a1) % 32768; }
void __fastcall g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; }
void __fastcall f2(int a1, int a2) { f1(a1); f1(a2); }
void __fastcall g2(int a1, int a2) const { g1(a1); g1(a2); }
void __fastcall f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); }
void __fastcall g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); }
void __fastcall f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); }
void __fastcall g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); }
void __fastcall f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); }
void __fastcall g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); }
void __fastcall f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); }
void __fastcall g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); }
void __fastcall f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); }
void __fastcall 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); }
void __fastcall 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); }
void __fastcall 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); }
};
int detect_errors(bool x)
{
if(x)
{
std::cerr << "no errors detected.\n";
return 0;
}
else
{
std::cerr << "test failed.\n";
return 1;
}
}
int main()
{
using boost::mem_fn;
X x;
X const & rcx = x;
X const * pcx = &x;
boost::shared_ptr<X> sp(new X);
mem_fn(&X::f0)(x);
mem_fn(&X::f0)(&x);
mem_fn(&X::f0)(sp);
mem_fn(&X::g0)(x);
mem_fn(&X::g0)(rcx);
mem_fn(&X::g0)(&x);
mem_fn(&X::g0)(pcx);
mem_fn(&X::g0)(sp);
mem_fn(&X::f1)(x, 1);
mem_fn(&X::f1)(&x, 1);
mem_fn(&X::f1)(sp, 1);
mem_fn(&X::g1)(x, 1);
mem_fn(&X::g1)(rcx, 1);
mem_fn(&X::g1)(&x, 1);
mem_fn(&X::g1)(pcx, 1);
mem_fn(&X::g1)(sp, 1);
mem_fn(&X::f2)(x, 1, 2);
mem_fn(&X::f2)(&x, 1, 2);
mem_fn(&X::f2)(sp, 1, 2);
mem_fn(&X::g2)(x, 1, 2);
mem_fn(&X::g2)(rcx, 1, 2);
mem_fn(&X::g2)(&x, 1, 2);
mem_fn(&X::g2)(pcx, 1, 2);
mem_fn(&X::g2)(sp, 1, 2);
mem_fn(&X::f3)(x, 1, 2, 3);
mem_fn(&X::f3)(&x, 1, 2, 3);
mem_fn(&X::f3)(sp, 1, 2, 3);
mem_fn(&X::g3)(x, 1, 2, 3);
mem_fn(&X::g3)(rcx, 1, 2, 3);
mem_fn(&X::g3)(&x, 1, 2, 3);
mem_fn(&X::g3)(pcx, 1, 2, 3);
mem_fn(&X::g3)(sp, 1, 2, 3);
mem_fn(&X::f4)(x, 1, 2, 3, 4);
mem_fn(&X::f4)(&x, 1, 2, 3, 4);
mem_fn(&X::f4)(sp, 1, 2, 3, 4);
mem_fn(&X::g4)(x, 1, 2, 3, 4);
mem_fn(&X::g4)(rcx, 1, 2, 3, 4);
mem_fn(&X::g4)(&x, 1, 2, 3, 4);
mem_fn(&X::g4)(pcx, 1, 2, 3, 4);
mem_fn(&X::g4)(sp, 1, 2, 3, 4);
mem_fn(&X::f5)(x, 1, 2, 3, 4, 5);
mem_fn(&X::f5)(&x, 1, 2, 3, 4, 5);
mem_fn(&X::f5)(sp, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(x, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(rcx, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(&x, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(pcx, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(sp, 1, 2, 3, 4, 5);
mem_fn(&X::f6)(x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::f6)(&x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::f6)(sp, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(rcx, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(&x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(pcx, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(sp, 1, 2, 3, 4, 5, 6);
mem_fn(&X::f7)(x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::f7)(&x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::f7)(sp, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(rcx, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(&x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(pcx, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(sp, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::f8)(x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::f8)(&x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::f8)(sp, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(rcx, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(&x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(pcx, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(sp, 1, 2, 3, 4, 5, 6, 7, 8);
return detect_errors(x.hash == 17610 && sp->hash == 2155);
}