diff --git a/bind.html b/bind.html index 5c8abca..8d965c2 100644 --- a/bind.html +++ b/bind.html @@ -76,8 +76,8 @@

Files

Dependencies

Number of Arguments

-

"__stdcall", "__fastcall", and - "pascal" Support

+

"__stdcall", "__cdecl", "__fastcall", + and "pascal" Support

visit_each support

Acknowledgements

Purpose

@@ -270,12 +270,13 @@ std::vector<pf> v; std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5)); -

Sometimes it is necessary not to evaluate the first argument, but not - to evaluate some of the other arguments, even when they are nested bind - subexpressions. This can be achieved with the help of another function object, - protect, that masks the type so that bind does - not recognize and evaluate it. When called, protect simply - forwards the argument list to the other function object unmodified.

+

Although the first argument is, by default, not evaluated, all other arguments + are. Sometimes it is necessary not to evaluate arguments subsequent to the + first, even when they are nested bind subexpressions. This can + be achieved with the help of another function object, protect, + that masks the type so that bind does not recognize and + evaluate it. When called, protect simply forwards the argument + list to the other function object unmodified.

The header boost/bind/protect.hpp contains an implementation of protect. To protect a bind function object from evaluation, use protect(bind(f, ...)).

@@ -795,7 +796,7 @@ namespace

Number of Arguments

This implementation supports function objects with up to nine arguments. This is an implementation detail, not an inherent limitation of the design.

-

"__stdcall", "__fastcall", and "pascal" Support

+

"__stdcall", "__cdecl", "__fastcall", and "pascal" Support

Some platforms allow several types of (member) functions that differ by their calling convention (the rules by which the function is invoked: how are arguments passed, how is the return value handled, and who cleans up the stack @@ -813,6 +814,12 @@ namespace the macro BOOST_MEM_FN_ENABLE_FASTCALL before including <boost/bind.hpp>.

To use bind with pascal functions, #define the macro BOOST_BIND_ENABLE_PASCAL before including <boost/bind.hpp>.

+

To use bind with __cdecl member functions, #define the + macro BOOST_MEM_FN_ENABLE_CDECL before including <boost/bind.hpp>.

+

It is best to define these macros in the project options, via -D on the + command line, or as the first line in the translation unit (.cpp file) where + bind is used. Not following this rule can lead to obscure errors + when a header includes bind.hpp before the macro has been defined.

[Note: this is a non-portable extension. It is not part of the interface.]

[Note: Some compilers provide only minimal support for the __stdcall keyword.]

visit_each support

@@ -857,10 +864,10 @@ namespace




- Copyright © 2001, 2002 by Peter Dimov and Multi Media Ltd. Permission to - copy, use, modify, sell and distribute this document is granted provided this - copyright notice appears in all copies. This document is provided "as is" - without express or implied warranty, and with no claim as to its suitability - for any purpose.

+ Copyright © 2001, 2002 by Peter Dimov and Multi Media Ltd. Copyright + 2003-2005 Peter Dimov. Permission to copy, use, modify, sell and distribute + this document is granted provided this copyright notice appears in all copies. + This document is provided "as is" without express or implied warranty, and with + no claim as to its suitability for any purpose.

diff --git a/include/boost/bind.hpp b/include/boost/bind.hpp index 5328f49..af91ddb 100644 --- a/include/boost/bind.hpp +++ b/include/boost/bind.hpp @@ -1422,6 +1422,18 @@ template + +#undef BOOST_BIND_MF_NAME +#undef BOOST_BIND_MF_CC + +#endif + #ifdef BOOST_MEM_FN_ENABLE_STDCALL #define BOOST_BIND_MF_NAME(X) X##_stdcall diff --git a/include/boost/mem_fn.hpp b/include/boost/mem_fn.hpp index dd46ef3..6b9c16d 100644 --- a/include/boost/mem_fn.hpp +++ b/include/boost/mem_fn.hpp @@ -12,6 +12,7 @@ // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2001 David Abrahams +// Copyright (c) 2003-2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -48,6 +49,18 @@ template struct mf #undef BOOST_MEM_FN_CC #undef BOOST_MEM_FN_NAME +#ifdef BOOST_MEM_FN_ENABLE_CDECL + +#define BOOST_MEM_FN_NAME(X) inner_##X##_cdecl +#define BOOST_MEM_FN_CC __cdecl + +#include + +#undef BOOST_MEM_FN_CC +#undef BOOST_MEM_FN_NAME + +#endif + #ifdef BOOST_MEM_FN_ENABLE_STDCALL #define BOOST_MEM_FN_NAME(X) inner_##X##_stdcall @@ -89,6 +102,18 @@ template<> struct mf #undef BOOST_MEM_FN_CC #undef BOOST_MEM_FN_NAME +#ifdef BOOST_MEM_FN_ENABLE_CDECL + +#define BOOST_MEM_FN_NAME(X) inner_##X##_cdecl +#define BOOST_MEM_FN_CC __cdecl + +#include + +#undef BOOST_MEM_FN_CC +#undef BOOST_MEM_FN_NAME + +#endif + #ifdef BOOST_MEM_FN_ENABLE_STDCALL #define BOOST_MEM_FN_NAME(X) inner_##X##_stdcall @@ -130,6 +155,20 @@ template<> struct mf #undef BOOST_MEM_FN_NAME2 #undef BOOST_MEM_FN_CC +#ifdef BOOST_MEM_FN_ENABLE_CDECL + +#define BOOST_MEM_FN_NAME(X) X##_cdecl +#define BOOST_MEM_FN_NAME2(X) inner_##X##_cdecl +#define BOOST_MEM_FN_CC __cdecl + +#include + +#undef BOOST_MEM_FN_NAME +#undef BOOST_MEM_FN_NAME2 +#undef BOOST_MEM_FN_CC + +#endif + #ifdef BOOST_MEM_FN_ENABLE_STDCALL #define BOOST_MEM_FN_NAME(X) X##_stdcall @@ -178,6 +217,18 @@ namespace _mfi #undef BOOST_MEM_FN_CC #undef BOOST_MEM_FN_NAME +#ifdef BOOST_MEM_FN_ENABLE_CDECL + +#define BOOST_MEM_FN_NAME(X) X##_cdecl +#define BOOST_MEM_FN_CC __cdecl + +#include + +#undef BOOST_MEM_FN_CC +#undef BOOST_MEM_FN_NAME + +#endif + #ifdef BOOST_MEM_FN_ENABLE_STDCALL #define BOOST_MEM_FN_NAME(X) X##_stdcall @@ -219,6 +270,18 @@ namespace _mfi #undef BOOST_MEM_FN_NAME #undef BOOST_MEM_FN_CC +#ifdef BOOST_MEM_FN_ENABLE_CDECL + +#define BOOST_MEM_FN_NAME(X) X##_cdecl +#define BOOST_MEM_FN_CC __cdecl + +#include + +#undef BOOST_MEM_FN_NAME +#undef BOOST_MEM_FN_CC + +#endif + #ifdef BOOST_MEM_FN_ENABLE_STDCALL #define BOOST_MEM_FN_NAME(X) X##_stdcall diff --git a/mem_fn.html b/mem_fn.html index 2d0da3c..0a506ac 100644 --- a/mem_fn.html +++ b/mem_fn.html @@ -37,8 +37,8 @@

Files

Dependencies

Number of Arguments

-

"__stdcall" and - "__fastcall" Support

+

"__stdcall", "__cdecl" and + "__fastcall" Support

Acknowledgements

Purpose

@@ -168,10 +168,13 @@ void k(std::vector<boost::shared_ptr<X> > const & v)

Why isn't BOOST_MEM_FN_ENABLE_STDCALL defined automatically?

- Non-portable extensions, in general, should default to off to prevent vendor - lock-in. Had BOOST_MEM_FN_ENABLE_STDCALL been defined automatically, you could - have accidentally taken advantage of it without realizing that your code is, - perhaps, no longer portable. + Non-portable extensions, in general, should default to +off to prevent vendor lock-in. Had BOOST_MEM_FN_ENABLE_STDCALL been defined +automatically, you could have accidentally taken advantage of + it without realizing that your code is, perhaps, no longer portable. + In addition, it is possible for the default + calling convention to be __stdcall, in which case enabling __stdcall support will + result in duplicate definitions.

Interface

Synopsis

@@ -346,7 +349,7 @@ template<class R, class T, class A1, class A2> unspecified-6 -

"__stdcall" and "__fastcall" Support

+

"__stdcall", "__cdecl" and "__fastcall" Support

Some platforms allow several types of member functions that differ by their calling convention (the rules by which the function is invoked: how are @@ -355,7 +358,8 @@ template<class R, class T, class A1, class A2> unspecified-6

For example, Windows API functions and COM interface member functions use a - calling convention known as __stdcall. Borland VCL components use __fastcall. + calling convention known as __stdcall. Borland VCL components use __fastcall. UDK, the component model of +OpenOffice.org, uses __cdecl.

To use mem_fn with __stdcall member functions, #define the @@ -363,11 +367,18 @@ template<class R, class T, class A1, class A2> unspecified-6 <boost/mem_fn.hpp>.

To use mem_fn with __fastcall member functions, #define the - macro BOOST_MEM_FN_ENABLE_FASTCALL before including, directly or - indirectly, <boost/mem_fn.hpp>. -

-

[Note: this is a non-portable extension. It is not part of the interface.] + macro BOOST_MEM_FN_ENABLE_FASTCALL before + including <boost/mem_fn.hpp>.

+

To use mem_fn with __cdecl member functions, #define the +macro BOOST_MEM_FN_ENABLE_CDECL before including +<boost/mem_fn.hpp>.

+

It is best to define these macros in the project options, via -D +on the command line, or as the first line in the translation unit (.cpp file) +where mem_fn is used. Not following this rule can lead to obscure +errors when a header includes mem_fn.hpp before the macro has been defined.

+

[Note: this is a non-portable extension. It is not part of the interface.] +

[Note: Some compilers provide only minimal support for the __stdcall keyword.]

@@ -387,10 +398,10 @@ template<class R, class T, class A1, class A2> unspecified-6
bind and mem_fn to support void returns on deficient compilers.

-


+

Daniel Boelzle pointed out that UDK uses __cdecl.


- Copyright © 2001, 2002 by Peter Dimov and Multi Media Ltd. Permission + Copyright © 2001, 2002 by Peter Dimov and Multi Media Ltd. Copyright 2003-2005 Peter Dimov. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability diff --git a/test/bind_cdecl_mf_test.cpp b/test/bind_cdecl_mf_test.cpp new file mode 100644 index 0000000..796411c --- /dev/null +++ b/test/bind_cdecl_mf_test.cpp @@ -0,0 +1,164 @@ +#include + +#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_cdecl_mf_test.cpp - test for bind.hpp + __cdecl (member functions) +// +// Copyright (c) 2005 Peter Dimov +// +// 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 + +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) +#pragma warning(push, 3) +#endif + +#include + +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) +#pragma warning(pop) +#endif + +#include + +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 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 main() +{ + member_function_test(); + return boost::report_errors(); +} diff --git a/test/mem_fn_cdecl_test.cpp b/test/mem_fn_cdecl_test.cpp new file mode 100644 index 0000000..ffe9723 --- /dev/null +++ b/test/mem_fn_cdecl_test.cpp @@ -0,0 +1,186 @@ +#include + +#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 + +// +// mem_fn_cdecl_test.cpp - a test for mem_fn.hpp + __cdecl +// +// Copyright (c) 2005 Peter Dimov +// +// 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 +#include + +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) +#pragma warning(push, 3) +#endif + +#include + +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) +#pragma warning(pop) +#endif + + +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; } +}; + +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 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); +}