From b90421d2cd0aa9250ce1be1fe6ef6db8ac973b71 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 6 Dec 2001 16:06:30 +0000 Subject: [PATCH] Troubleshooting section updated. [SVN r11954] --- bind.html | 285 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 235 insertions(+), 50 deletions(-) diff --git a/bind.html b/bind.html index 6457c4d..258d9e0 100644 --- a/bind.html +++ b/bind.html @@ -38,15 +38,25 @@

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.]

Frequently Asked Questions

-

Why doesn't this compile?

+

Why doesn't this compile?

See the dedicated Troubleshooting section.

-

Why does this compile? It should not.

+

Why does this compile? It should not.

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.

-

What is the difference between bind(f, ...) and bind<R>(f, ...)?

+

What is the difference between bind(f, ...) and bind<R>(f, ...)?

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.

-

Does bind work with Windows API functions?

+

Does bind work with Windows API functions?

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.

-

Does bind work with COM methods?

+

Does bind work with COM methods?

Yes, if you #define BOOST_MEM_FN_ENABLE_STDCALL.

-

Does bind work with Mac toolbox functions?

+

Does bind work with Mac toolbox functions?

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.

-

Why doesn't bind automatically recognize nonstandard functions?

+

Why doesn't bind automatically recognize nonstandard functions?

Non-portable extensions, in general, should default to off to prevent vendor @@ -509,10 +519,208 @@ separate support would be necessary.

Troubleshooting

+

Incorrect number of arguments

+

-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
+}
+
+ +

The function object cannot be called with the specified arguments

+ +

+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
+}
+
+ +

Accessing an argument that does not exist

+ +

+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). +

+ +

Inappropriate use of bind(f, ...)

+ +

+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. +

+ +

Inappropriate use of bind<R>(f, ...)

+ +

+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. +

+ +

Binding a nonstandard function

+ +

+(to be written) +

+ +

MSVC specific: using boost::bind;

+ +On MSVC (up to version 7.0), when boost::bind is brought into scope +with an using declaration: +

+ +
+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;
+
+ +

MSVC specific: class templates shadow function templates

+ +

+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 specific: const in signatures

+ +

+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 specific: ... in signatures treated as type

+ +

+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);
+
+

Interface

Synopsis

@@ -779,39 +987,16 @@ To use bind with pascal functions, #define the macro [Note: Some compilers provide only minimal support for the __stdcall keyword.]

-

MSVC specific problems and workarounds

+

Using the BOOST_BIND macro

-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.