From b90421d2cd0aa9250ce1be1fe6ef6db8ac973b71 Mon Sep 17 00:00:00 2001
From: Peter Dimov Limitations
Frequently Asked Questions
-Why doesn't this compile?
-Why does this compile? It should not.
-What is the difference between bind(f, ...) and bind<R>(f, ...)?
-Does bind work with Windows API functions?
-Does bind work with COM methods?
-Does bind work with Mac toolbox functions?
-Why doesn't bind automatically recognize nonstandard functions?
+Why doesn't this compile?
+Why does this compile? It should not.
+What is the difference between bind(f, ...) and bind<R>(f, ...)?
+Does bind work with Windows API functions?
+Does bind work with COM methods?
+Does bind work with Mac toolbox functions?
+Why doesn't bind automatically recognize nonstandard functions?
Troubleshooting
+Incorrect number of arguments
+The function object cannot be called with the specified arguments
+Accessing an argument that does not exist
+Inappropriate use of bind(f, ...)
+Inappropriate use of bind<R>(f, ...)
+Binding a nonstandard function
+MSVC specific: using boost::bind;
+MSVC specific: class templates shadow function templates
+MSVC specific: const in signatures
+MSVC specific: ... in signatures treated as type
Interface
Synopsis
@@ -59,7 +69,7 @@
Dependencies
Number of Arguments
"__stdcall" and "pascal" Support
-MSVC specific problems and workarounds
+Using the BOOST_BIND macro
visit_each support
Acknowledgements
@@ -111,15 +121,15 @@ library primitives:
-std::bind1st(std::ptr_fun(f), 5)(x); +std::bind2nd(std::ptr_fun(f), 5)(x);
-bind covers the functionality of std::bind2nd as well: +bind covers the functionality of std::bind1st as well:
-std::bind2nd(std::ptr_fun(f), 5)(x); // f(5, x) +std::bind1st(std::ptr_fun(f), 5)(x); // f(5, x) bind(f, 5, _1)(x); // f(5, x)@@ -429,13 +439,13 @@ corresponding issue has not been resolved yet.]
See the dedicated Troubleshooting section.
-Probably because you used the general bind<R>(f, ...) syntax, thereby @@ -443,7 +453,7 @@ instructing bind to not "inspect" f to detect arity and return type errors.
-The first form instructs bind to inspect the type of f in order @@ -471,7 +481,7 @@ first form when f is a function object, and in most cases will not handle the second form when f is a function (pointer) or a member function pointer.
-Yes, if you #define BOOST_BIND_ENABLE_STDCALL. @@ -480,13 +490,13 @@ An alternative is to treat the function as a bind<R>(f, ...) syntax.
-Yes, if you #define BOOST_MEM_FN_ENABLE_STDCALL.
-Yes, if you #define BOOST_BIND_ENABLE_PASCAL. @@ -495,7 +505,7 @@ An alternative is to treat the function as a bind<R>(f, ...) syntax.
-Non-portable extensions, in general, should default to off to prevent vendor @@ -509,10 +519,208 @@ separate support would be necessary.
-This section is still under development. +In a bind(f, a1, a2, ..., aN) expression, the function object f must +be able to take exactly N arguments. This error is normally detected +at "bind time"; in other words, the compilation error is reported +on the line where bind() is invoked:
++int f(int, int); + +int main() +{ + boost::bind(f, 1); // error, f takes two arguments + boost::bind(f, 1, 2); // OK +} ++ +
+A common variation of this error is to forget that member functions have an +implicit "this" argument: +
+ ++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 +} ++ +
+As in normal function calls, the function object that is bound must be +compatible with the argument list. The incompatibility will usually be +detected by the compiler at "call time" and the result is +typically an error in bind.hpp on a line that looks like: +
+ ++ return f(a[a1_], a[a2_]); ++ +
+An example of this kind of error: +
+ ++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 +} ++ +
+The placeholder _N selects the argument at position N from the +argument list passed at "call time." Naturally, it is an error to +attempt to access beyond the end of this list: +
+ ++int f(int); + +int main() +{ + boost::bind(f, _1); // OK + boost::bind(f, _1)(); // error, there is no argument number 1 +} ++ +
+The error is usually reported in bind.hpp, at a line similar to: +
+ ++ A2 operator[] (arg<2>) const { return a2_; } ++ +
+When emulating std::bind1st(f, a), a common mistake of this category +is to type bind(f, a, _2) instead of the correct bind(f, a, _1). +
+ ++The bind(f, a1, a2, ..., aN) form causes automatic +recognition of the type of f. It will not work with arbitrary +function objects; f must be a function or a member function pointer. +
+ ++It is possible to use this form with function objects that define +result_type, but only on compilers that support partial +specialization and partial ordering. In particular, MSVC up to version 7.0 +does not support this syntax for function objects. +
+ ++The bind<R>(f, a1, a2, ..., aN) form supports +arbitrary function objects. +
+ ++It is possible (but not recommended) to use this form with functions or +member function pointers, but only on compilers that support partial +ordering. In particular, MSVC up to version 7.0 does not fully support this +syntax for functions and member function pointers. +
+ ++(to be written) +
+ ++using boost::bind; ++ +
+the syntax bind<R>(...) does not work. Workaround: either use the +qualified name, boost::bind, or use an using directive instead: +
+ ++using namespace boost; ++ +
+On MSVC (up to version 7.0), a nested class template named bind will +shadow the function template boost::bind, breaking the +bind<R>(...) syntax. Unfortunately, some libraries contain nested +class templates named bind (ironically, such code is often an MSVC +specific workaround.) You may try to patch the library in question or contact +its author/maintainer. The other option is use the +BOOST_BIND macro to rename bind. +
+ ++MSVC 6.0 has problems with const in function signatures: +
+ ++int f(int const); + +int main() +{ + boost::bind(f, 1); // error +} ++ +
+Workaround: remove the const qualifier from the argument. +
+ ++MSVC (up to version 7.0) treats the ellipsis in a variable argument function +(such as std::printf) as a type. Therefore, it will accept the +(incorrect in the current implementation) form: +
+ ++ bind(printf, "%s\n", _1); ++ +
+and will reject the correct version: +
+ ++ bind<int>(printf, "%s\n", _1); ++
-Microsoft Visual C++ (up to version 7.0) does not fully support the -bind<R>(...) -syntax required by the library when arbitrary function objects are bound. -The first problem is that when boost::bind is brought into scope -with an using declaration: -
- --using boost::bind; -- -
-the syntax above does not work. Workaround: either use the qualified name, -boost::bind, or use an using directive instead: -
- --using namespace boost; -- -
-The second problem is that some libraries contain nested class templates -named bind (ironically, such code is often an MSVC specific -workaround.) Due to some quirks with the parser, such a class template -breaks the bind<R>(...) syntax, even when the name bind -is fully qualified. You may try to patch the library in question or contact -its author/maintainer. The other option is to define the macro -BOOST_BIND to something other than bind (before the inclusion of -<boost/bind.hpp>) and use this identifier throughout your code -wherever you'd normally use bind. +A bug in MSVC (up to version 7.0) +causes boost::bind to be incompatible +with libraries that contain nested class templates named bind. To work +around this problem, #define the macro BOOST_BIND to something +other than bind (before the inclusion of <boost/bind.hpp>) +and use this identifier throughout your code wherever you'd normally use +bind.