版权所有 © 2001, 2002 Peter Dimov 和 Multi Media Ltd.
版权所有 © 2003-2008 Peter Dimov
根据 Boost 软件许可证,版本 1.0分发。
boost::bind
是标准函数 std::bind1st
和 std::bind2nd
的泛化。它支持任意函数对象、函数、函数指针和成员函数指针,并且能够将任何参数绑定到特定值或将输入参数路由到任意位置。bind
对函数对象没有任何要求;特别是,它不需要 result_type
、first_argument_type
和 second_argument_type
标准类型定义。
给定这些定义
int f(int a, int b) { return a + b; } int g(int a, int b, int c) { return a + b + c; }
bind(f, 1, 2)
将生成一个“零元”函数对象,它不接受任何参数并返回 f(1, 2)
。类似地,bind(g, 1, 2, 3)()
等效于 g(1, 2, 3)
。
可以选择性地只绑定某些参数。 bind(f, _1, 5)(x)
等效于 f(x, 5)
;这里 _1
是一个 占位符 参数,表示“用第一个输入参数替换”。
为了比较,以下是使用标准库原语表达的相同操作
std::bind2nd(std::ptr_fun(f), 5)(x);
bind
也涵盖了 std::bind1st
的功能
std::bind1st(std::ptr_fun(f), 5)(x); // f(5, x) bind(f, 5, _1)(x); // f(5, x)
bind
可以处理超过两个参数的函数,其参数替换机制更通用
bind(f, _2, _1)(x, y); // f(y, x) bind(g, _1, 9, _1)(x); // g(x, 9, x) bind(g, _3, _3, _3)(x, y, z); // g(z, z, z) bind(g, _1, _1, _1)(x, y, z); // g(x, x, x)
请注意,在最后一个示例中,由 bind(g, _1, _1, _1)
生成的函数对象不包含对第一个参数以外的任何参数的引用,但它仍然可以与多个参数一起使用。任何额外的参数都会被静默忽略,就像第三个示例中忽略第一个和第二个参数一样。
bind
接受的参数会被复制并由返回的函数对象内部保存。例如,在以下代码中
int i = 5; bind(f, i, _1);
将 i
的值的一个副本存储到函数对象中。boost::ref
和 boost::cref
可用于使函数对象存储对对象的引用,而不是副本
int i = 5; bind(f, ref(i), _1); bind(f, cref(i), _1);
bind
不仅限于函数;它接受任意函数对象。在一般情况下,生成的函数对象的 operator()
的返回类型必须显式指定(如果没有 typeof
运算符,则无法推断返回类型)
struct F { int operator()(int a, int b) { return a - b; } bool operator()(long a, long b) { return a == b; } }; F f; int x = 104; bind<int>(f, _1, _1)(x); // f(x, x), i.e. zero
某些编译器在使用 bind<R>(f, ...)
语法时遇到问题。出于可移植性原因,支持另一种表达上述内容的方法
boost::bind(boost::type<int>(), f, _1, _1)(x);
但是,请注意,备选语法仅作为解决方法提供。它不是接口的一部分。
当函数对象公开名为 result_type
的嵌套类型时,可以省略显式返回类型
int x = 8; bind(std::less<int>(), _1, 9)(x); // x < 9
[注意:并非所有编译器都支持省略返回类型。]
默认情况下,bind
会复制提供的函数对象。boost::ref
和 boost::cref
可用于使其存储对函数对象的引用,而不是副本。当函数对象不可复制、复制成本高昂或包含状态时,这很有用;当然,在这种情况下,程序员应确保在函数对象仍在使用时不会将其销毁。
struct F2 { int s; typedef void result_type; void operator()(int x) { s += x; } }; F2 f2 = { 0 }; int a[] = { 1, 2, 3 }; std::for_each(a, a+3, bind(ref(f2), _1)); assert(f2.s == 6);
成员函数指针和数据成员指针不是函数对象,因为它们不支持 operator()
。为方便起见,bind
接受成员指针作为其第一个参数,其行为就好像使用了 boost::mem_fn
将成员指针转换为函数对象一样。换句话说,表达式
bind(&X::f, args)
等效于
bind<R>(mem_fn
(&X::f), args)
其中 R
是 X::f
的返回类型(对于成员函数)或成员的类型(对于数据成员)。
[注意: mem_fn
创建能够接受指向对象的指针、引用或智能指针作为其第一个参数的函数对象;有关更多信息,请参阅 mem_fn
的 文档。]
示例
struct X { bool f(int a); }; X x; shared_ptr<X> p(new X); int i = 5; bind(&X::f, ref(x), _1)(i); // x.f(i) bind(&X::f, &x, _1)(i); // (&x)->f(i) bind(&X::f, x, _1)(i); // (internal copy of x).f(i) bind(&X::f, p, _1)(i); // (internal copy of p)->f(i)
最后两个例子很有趣,因为它们生成了“自包含”的函数对象。bind(&X::f, x, _1)
存储了x
的一个副本。bind(&X::f, p, _1)
存储了p
的一个副本,并且由于p
是一个boost::shared_ptr
,函数对象保留了对X
实例的引用,即使p
超出作用域或被reset()
,它仍然有效。
传递给bind
的一些参数本身可能是嵌套的bind表达式
bind(f, bind(g, _1))(x); // f(g(x))
当调用函数对象时,内部bind表达式以未指定的顺序进行求值,先于外部bind
;然后,在求值外部bind
时,将求值的结果替换到它们的位置。在上面的例子中,当用参数列表(x)
调用函数对象时,bind(g, _1)(x)
首先被求值,得到g(x)
,然后bind(f, g(x))(x)
被求值,得到最终结果f(g(x))
。
bind
的这个特性可以用来执行函数组合。参见bind_as_compose.cpp,其中有一个例子演示了如何使用bind
来实现与Boost.Compose类似的功能。
注意,第一个参数——绑定的函数对象——不会被求值,即使它是由bind
生成的函数对象或一个占位符参数,所以下面的例子不会按预期工作。
typedef void (*pf)(int); std::vector<pf> v; std::for_each(v.begin(), v.end(), bind(_1, 5));
可以通过一个辅助函数对象apply
来实现所需的效果,该对象将其第一个参数(作为函数对象)应用于其参数列表的其余部分。为方便起见,apply
的实现已提供在apply.hpp头文件中。以下是修改后的上一例子的样子。
typedef void (*pf)(int); std::vector<pf> v; std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));
尽管第一个参数默认情况下不会被求值,但所有其他参数都会被求值。有时需要不求值第一个参数之后的参数,即使它们是嵌套的bind子表达式。这可以使用另一个函数对象protect
来实现,该对象会屏蔽类型,以便bind
无法识别和求值它。当被调用时,protect
只是简单地将参数列表未修改地转发给另一个函数对象。
protect.hpp头文件包含protect
的实现。要protect
一个bind函数对象免于求值,可以使用protect(bind(f, ...))
。
为方便起见,由bind
生成的函数对象重载了逻辑非运算符!
和关系和逻辑运算符==, !=, <, <=, >, >=, &&, ||
。
!bind(f, ...)
等价于bind(logical_not(), bind(f, ...))
,其中logical_not
是一个函数对象,它接受一个参数x
并返回!x
。
bind(f, ...) op x
,其中op是一个关系或逻辑运算符,等价于bind(relation(), bind(f, ...), x)
,其中relation
是一个函数对象,它接受两个参数a
和b
并返回a op b
。
在实践中,这意味着您可以方便地否定bind
的结果。
std::remove_if(first, last, !bind(&X::visible, _1)); // remove invisible objects
并将bind
的结果与一个值进行比较。
std::find_if(first, last, bind(&X::name, _1) == "Peter"); std::find_if(first, last, bind(&X::name, _1) == "Peter" || bind(&X::name, _1) == "Paul");
与一个占位符进行比较。
bind(&X::name, _1) == _2
或与另一个bind表达式进行比较。
std::sort(first, last, bind(&X::name, _1) < bind(&X::name, _2)); // sort by name
class image; class animation { public: void advance(int ms); bool inactive() const; void render(image & target) const; }; std::vector<animation> anims; template<class C, class P> void erase_if(C & c, P pred) { c.erase(std::remove_if(c.begin(), c.end(), pred), c.end()); } void update(int ms) { std::for_each(anims.begin(), anims.end(), boost::bind(&animation::advance, _1, ms)); erase_if(anims, boost::mem_fn(&animation::inactive)); } void render(image & target) { std::for_each(anims.begin(), anims.end(), boost::bind(&animation::render, _1, boost::ref(target))); }
class button
{
public:
boost::function
<void()> onClick;
};
class player
{
public:
void play();
void stop();
};
button playButton, stopButton;
player thePlayer;
void connect()
{
playButton.onClick = boost::bind(&player::play, &thePlayer);
stopButton.onClick = boost::bind(&player::stop, &thePlayer);
}
一般来说,由bind
生成的函数对象按引用获取其参数,因此不能接受非常量临时变量或文字常量。这是当前(2003 年)C++语言固有的限制,称为转发问题。(它将在下一个标准(通常称为C++0x)中得到修复。)
库使用以下形式的签名:
template<class T> void f(T & t);
来接受任意类型的参数并将其未修改地传递。如前所述,这对非常量右值不起作用。
在支持函数模板部分排序的编译器上,一个可能的解决方案是添加一个重载:
template<class T> void f(T & t); template<class T> void f(T const & t);
不幸的是,这需要为九个参数提供 512 个重载,这是不切实际的。库选择了一个小的子集:对于最多两个参数,它完全提供了 const 重载;对于三个或更多个参数,它提供了一个额外的重载,所有参数都通过 const 引用获取。这涵盖了相当一部分用例。
可能是因为您使用了通用的bind<R>(f, ...)
语法,从而指示bind
不“检查”f 以检测参数个数和返回类型错误。
第一种形式指示bind
检查f
的类型以确定其参数个数和返回类型。参数个数错误将在“bind 时间”被检测到。当然,此语法对f
提出了一些要求。它必须是一个函数、函数指针、成员函数指针或定义名为result_type
的嵌套类型的函数对象;简而言之,它必须是bind
可以识别的东西。
第二种形式指示bind
不要尝试识别f
的类型。它通常与不公开或无法公开result_type
的函数对象一起使用,但也可以与非标准函数一起使用。例如,当前实现不会自动识别可变参数函数(如printf
),因此您必须使用bind<int>(printf, ...)
。请注意,出于可移植性原因,支持替代的bind(type<R>(), f, ...)
语法。
另一个需要考虑的重要因素是,不支持部分模板特化或函数模板部分排序的编译器在f
是函数对象时无法处理第一种形式,并且在大多数情况下,在f
是函数(指针)或成员函数指针时无法处理第二种形式。
是的,如果您#define BOOST_BIND_ENABLE_STDCALL
。另一种方法是将函数视为泛型函数对象,并使用bind<R>(f, ...)
语法。
是的,如果您#define BOOST_BIND_ENABLE_PASCAL
。另一种方法是将函数视为泛型函数对象,并使用bind<R>(f, ...)
语法。
有时可以。在某些平台上,指向 extern "C" 函数的指针等同于“普通”函数指针,因此它们可以正常工作。其他平台将它们视为不同的类型。bind
的特定于平台的实现应该能够透明地处理这个问题;此实现则不能。像往常一样,解决方法是将函数视为泛型函数对象,并使用bind<R>(f, ...)
语法。
一般来说,非可移植扩展应该默认为关闭,以防止厂商锁定。如果相应的宏被自动定义,您可能会在没有意识到代码可能不再可移植的情况下意外地利用它们。此外,一些编译器可以选择将__stdcall
(__fastcall
)设为默认调用约定,在这种情况下,无需单独的支持。
在bind(f, a1, a2, ..., aN)
表达式中,函数对象f
必须能够恰好接受N个参数。此错误通常在“绑定时”检测到;换句话说,编译错误是在调用bind()
的行上报告的。
int f(int, int); int main() { boost::bind(f, 1); // error, f takes two arguments boost::bind(f, 1, 2); // OK }
此错误的一个常见变体是忘记成员函数有一个隐式的“this”参数。
struct X { int f(int); } int main() { boost::bind(&X::f, 1); // error, X::f takes two arguments boost::bind(&X::f, _1, 1); // OK }
与正常的函数调用一样,绑定的函数对象必须与参数列表兼容。不兼容通常会在“调用时”由编译器检测到,结果通常是在bind.hpp
中的一行出现错误,类似于:
return f(a[a1_], a[a2_]);
此类错误的一个示例:
int f(int); int main() { boost::bind(f, "incompatible"); // OK so far, no call boost::bind(f, "incompatible")(); // error, "incompatible" is not an int boost::bind(f, _1); // OK boost::bind(f, _1)("incompatible"); // error, "incompatible" is not an int }
占位符_N
从“调用时”传递的参数列表中选择位置N
处的参数。当然,尝试访问此列表的末尾之后是一个错误。
int f(int); int main() { boost::bind(f, _1); // OK boost::bind(f, _1)(); // error, there is no argument number 1 }
错误通常在bind.hpp
中报告,类似于以下行:
return f(a[a1_]);
在模拟std::bind1st(f, a)
时,此类错误的一个常见错误是键入bind(f, a, _2)
而不是正确的bind(f, a, _1)
。
bind(f, a1, a2, ..., aN)
形式会自动识别f
的类型。它不适用于任意函数对象;f
必须是函数或成员函数指针。
可以使用此形式与定义了result_type
的函数对象一起使用,但仅限于支持部分特化和部分排序的编译器。特别是,直到 7.0 版本的 MSVC 都不支持函数对象的此语法。
bind<R>(f, a1, a2, ..., aN)
形式支持任意函数对象。
可以使用此形式与函数或成员函数指针一起使用(但不推荐),但仅限于支持部分排序的编译器。特别是,直到 7.0 版本的 MSVC 并不完全支持函数和成员函数指针的此语法。
默认情况下,bind(f, a1, a2, ..., aN)
形式识别“普通”C++函数和函数指针。使用不同调用约定的函数或可变参数函数(例如std::printf
)不起作用。通用bind<R>(f, a1, a2, ..., aN)
形式适用于非标准函数。
在某些平台上,像std::strcmp
这样的 extern "C" 函数不被bind
的简短形式识别。
另请参见__stdcall
和pascal
支持。
尝试绑定重载函数通常会导致错误,因为无法确定要绑定哪个重载。对于具有两个重载(const 和非 const)的成员函数来说,这是一个常见问题,例如在这个简化的示例中:
struct X { int& get(); int const& get() const; }; int main() { boost::bind(&X::get, _1); }
可以通过将(成员)函数指针强制转换为所需类型来手动解决歧义。
int main() { boost::bind(static_cast< int const& (X::*) () const >(&X::get), _1); }
另一个可以说是更易读的替代方法是引入一个临时变量。
int main() { int const& (X::*get) () const = &X::get; boost::bind(get, _1); }
由 bind
生成的函数对象并不符合 STL 的 一元函数 或 二元函数 概念,即使这些函数对象是一元或二元操作,因为这些函数对象的类型缺少公共类型定义 result_type
和 argument_type
或 first_argument_type
和 second_argument_type
。但是,在需要这些类型定义的情况下,可以使用实用程序函数 make_adaptable
将一元和二元函数对象适配到这些概念。这允许将 bind
生成的 一元和二元函数对象与 STL 模板(例如 std::unary_negate
和 std::binary_negate
)结合使用。
make_adaptable
函数定义在 <boost/bind/make_adaptable.hpp>
中,除了 <boost/bind/bind.hpp>
之外,还必须显式包含该文件。
#include <boost/bind/make_adaptable.hpp> template <class R, class F> unspecified-type make_adaptable(F f); template<class R, class A1, class F> unspecified-unary-functional-type make_adaptable(F f); template<class R, class A1, class A2, class F> unspecified-binary-functional-type make_adaptable(F f); template<class R, class A1, class A2, class A3, class F> unspecified-ternary-functional-type make_adaptable(F f); template<class R, class A1, class A2, class A3, class A4, class F> unspecified-4-ary-functional-type make_adaptable(F f);
此示例演示如何使用 make_adaptable
创建一个“不是空格”的谓词。
typedef char char_t; std::locale loc(""); const std::ctype<char_t>& ct = std::use_facet<std::ctype<char_t> >(loc); auto isntspace = std::not1(boost::make_adaptable<bool, char_t>(boost::bind(&std::ctype<char_t>::is, &ct, std::ctype_base::space, _1)));
在此示例中,bind
创建“是空格”(一元)谓词。然后将其传递给 make_adaptable
,以便可以创建一个符合 一元函数 概念的函数对象,作为 std::not1
的参数。
一些编译器,包括 MSVC 6.0 和 Borland C++ 5.5.1,在函数签名中的顶层 const
方面存在问题。
int f(int const); int main() { boost::bind(f, 1); // error }
解决方法:从参数中删除 const
限定符。
在 MSVC(最高到 7.0 版本)中,当使用 using 声明将 boost::bind
引入作用域时
using boost::bind;
语法 bind<R>(f, ...)
将不起作用。解决方法:要么使用限定名称 boost::bind
,要么改用 using 指令。
using namespace boost;
在 MSVC(最高到 7.0 版本)中,名为 bind
的嵌套类模板将屏蔽函数模板 boost::bind
,从而破坏 bind<R>(f, ...)
语法。不幸的是,一些库包含名为 bind
的嵌套类模板(具有讽刺意味的是,此类代码通常是 MSVC 的特定解决方法)。
解决方法是使用备用 bind(type<R>(), f, ...)
语法。
MSVC(最高到 7.0 版本)将可变参数函数(例如 std::printf
)中的省略号视为类型。因此,它将接受(在当前实现中不正确)的形式
bind(printf, "%s\n", _1);
并将拒绝正确的版本
bind<int>(printf, "%s\n", _1);
namespace boost { // no arguments template<class R, class F> unspecified-1bind
(F f); template<class F> unspecified-1-1bind
(F f); template<class R> unspecified-2bind
(R (*f) ()); // one argument template<class R, class F, class A1> unspecified-3bind
(F f, A1 a1); template<class F, class A1> unspecified-3-1bind
(F f, A1 a1); template<class R, class B1, class A1> unspecified-4bind
(R (*f) (B1), A1 a1); template<class R, class T, class A1> unspecified-5bind
(R (T::*f) (), A1 a1); template<class R, class T, class A1> unspecified-6bind
(R (T::*f) () const, A1 a1); template<class R, class T, class A1> unspecified-6-1bind
(R T::*f, A1 a1); // two arguments template<class R, class F, class A1, class A2> unspecified-7bind
(F f, A1 a1, A2 a2); template<class F, class A1, class A2> unspecified-7-1bind
(F f, A1 a1, A2 a2); template<class R, class B1, class B2, class A1, class A2> unspecified-8bind
(R (*f) (B1, B2), A1 a1, A2 a2); template<class R, class T, class B1, class A1, class A2> unspecified-9bind
(R (T::*f) (B1), A1 a1, A2 a2); template<class R, class T, class B1, class A1, class A2> unspecified-10bind
(R (T::*f) (B1) const, A1 a1, A2 a2); // implementation defined number of additional overloads for more arguments } namespace { unspecified-placeholder-type-1 _1; unspecified-placeholder-type-2 _2; unspecified-placeholder-type-3 _3; // implementation defined number of additional placeholder definitions }
所有 未指定-N 类型(由 bind
返回)都是 可复制构造 的。未指定-N::result_type
定义为 未指定-N::operator()
的返回类型。
所有 未指定占位符-N 类型都是 可复制构造 的。它们的复制构造函数不会抛出异常。
函数 μ(x, v1, v2, ..., vm)
(其中 m
是一个非负整数)定义为:
x.get()
,当 x
的类型为 boost::reference_wrapper
<T>
(对于某种类型 T
)时;vk
,当 x
是(某个)占位符 _k 的副本(对于某个正整数 k)时;x(v1, v2, ..., vm)
,当 x
是由 bind
返回的函数对象的副本时;x
。template<class R, class F> unspecified-1 bind(F f)
(v1, v2, ..., vm)
等价于 f()
(隐式转换为 R
)。F
的复制构造函数抛出异常,否则不抛出任何异常。template<class F> unspecified-1-1 bind(F f)
bind<typename F::result_type, F>(f)
。f
的返回类型作为扩展,而不依赖于 result_type
成员。template<class R> unspecified-2 bind(R (*f) ())
(v1, v2, ..., vm)
等价于 f()
。template<class R, class F, class A1> unspecified-3 bind(F f, A1 a1)
(v1, v2, ..., vm)
等价于 f(
μ(a1, v1, v2, ..., vm))
(隐式转换为 R
)。F
或 A1
的复制构造函数抛出异常,否则不抛出任何异常。template<class F, class A1> unspecified-3-1 bind(F f, A1 a1)
bind<typename F::result_type, F, A1>(f, a1)
。f
的返回类型作为扩展,而不依赖于 result_type
成员。template<class R, class B1, class A1> unspecified-4 bind(R (*f) (B1), A1 a1)
(v1, v2, ..., vm)
等效于 f(
μ(a1, v1, v2, ..., vm))
。A1
的复制构造函数抛出异常,否则不抛出任何异常。template<class R, class T, class A1> unspecified-5 bind(R (T::*f) (), A1 a1)
bind<R>(
boost::mem_fn
(f), a1)
。template<class R, class T, class A1> unspecified-6 bind(R (T::*f) () const, A1 a1)
bind<R>(
boost::mem_fn
(f), a1)
。template<class R, class T, class A1> unspecified-6-1 bind(R T::*f, A1 a1)
bind<R>(
boost::mem_fn
(f), a1)
。template<class R, class F, class A1, class A2> unspecified-7 bind(F f, A1 a1, A2 a2)
(v1, v2, ..., vm)
等效于 f(
μ(a1, v1, v2, ..., vm),
μ(a2, v1, v2, ..., vm))
,隐式转换为 R
。F
、A1
或 A2
的复制构造函数抛出异常,否则不抛出任何异常。template<class F, class A1, class A2> unspecified-7-1 bind(F f, A1 a1, A2 a2)
bind<typename F::result_type, F, A1, A2>(f, a1, a2)
。f
的返回类型作为扩展,而不依赖于 result_type
成员。template<class R, class B1, class B2, class A1, class A2> unspecified-8 bind(R (*f) (B1, B2), A1 a1, A2 a2)
(v1, v2, ..., vm)
等效于 f(
μ(a1, v1, v2, ..., vm),
μ(a2, v1, v2, ..., vm))
。A1
或 A2
的复制构造函数抛出异常,否则不抛出任何异常。template<class R, class T, class B1, class A1, class A2> unspecified-9 bind(R (T::*f) (B1), A1 a1, A2 a2)
bind<R>(
boost::mem_fn
(f), a1, a2)
。template<class R, class T, class B1, class A1, class A2> unspecified-10 bind(R (T::*f) (B1) const, A1 a1, A2 a2)
bind<R>(
boost::mem_fn
(f), a1, a2)
。允许实现提供额外的 bind
重载,以支持更多参数或不同的函数指针变体。
bind.hpp
使用,请勿直接包含)bind.hpp
使用,请勿直接包含)bind.hpp
使用,请勿直接包含)_1
、_2
、… _9
占位符)apply
辅助函数对象)protect
辅助函数)make_adaptable
辅助函数)__stdcall
函数的测试)__stdcall
成员函数的测试)__fastcall
函数的测试)__fastcall
成员函数的测试)此实现支持最多九个参数的函数对象。这是实现细节,而不是设计的固有限制。
某些平台允许几种类型的(成员)函数,这些函数的调用约定不同(函数调用的规则:如何传递参数、如何处理返回值以及谁清理堆栈——如果有的话)。
例如,Windows API 函数和 COM 接口成员函数使用称为 __stdcall
的调用约定。Borland VCL 组件使用 __fastcall
。Mac 工具箱函数使用 pascal
调用约定。
要在使用 __stdcall
函数时使用 bind
,请在包含 <boost/bind/bind.hpp>
之前定义宏 BOOST_BIND_ENABLE_STDCALL
。
要在使用 __stdcall
成员函数时使用 bind
,请在包含 <boost/bind/bind.hpp>
之前定义宏 BOOST_MEM_FN_ENABLE_STDCALL
。
要在使用 __fastcall
函数时使用 bind
,请在包含 <boost/bind/bind.hpp>
之前定义宏 BOOST_BIND_ENABLE_FASTCALL
。
要在使用 __fastcall
成员函数时使用 bind
,请在包含 <boost/bind/bind.hpp>
之前定义宏 BOOST_MEM_FN_ENABLE_FASTCALL
。
要将bind
与pascal
函数一起使用,请在包含<boost/bind/bind.hpp>
之前#define
宏BOOST_BIND_ENABLE_PASCAL
。
要将bind
与__cdecl
成员函数一起使用,请在包含<boost/bind/bind.hpp>
之前#define
宏BOOST_MEM_FN_ENABLE_CDECL
。
最好在项目选项中定义这些宏,例如在命令行使用-D
,或者作为使用bind
的翻译单元(.cpp 文件)的第一行。 不遵循此规则可能会导致在头文件包含bind.hpp
之前宏未定义时出现难以理解的错误。
[注意:这是一个非可移植的扩展。它不是接口的一部分。]
[注意:一些编译器仅对__stdcall
关键字提供有限的支持。]
影响库设计的一些早期工作
Doug Gregor 建议使用访问者机制可以让bind
与信号/槽库互操作。
John Maddock 修复了bind
和类型特性库之间特定于 MSVC 的冲突。
在正式评审期间,Ross Smith、Richard Crossley、Jens Maurer、Ed Brey 和其他人提出了许多改进建议。评审经理是 Darin Adler。
在与 Jaakko Järvi 的讨论中,对bind
的精确语义进行了改进。
Dave Abrahams 修复了bind
和迭代器适配器库之间特定于 MSVC 的冲突。
Dave Abrahams 修改了bind
和mem_fn
以在有缺陷的编译器上支持void
返回值。
Mac Murrett 贡献了由BOOST_BIND_ENABLE_PASCAL
启用的“pascal”支持。
替代的bind(type<R>(), f, ...)
语法受到了与 Dave Abrahams 和 Joel de Guzman 讨论的启发。
本文档由 Agustín Bergé 移植到 Quickbook。