Is there any way to use boost::function and member function pointers with
VC6 . I realize it is deficient in partial specialization but I was still
hoping to be able to use it. All my attempts to compile meet with failure
although the compiler tests say that VC6 succeeds both with boost::function
and boost::bind.
If I try the bind1st.cpp example in libs\function\example directory I get
the error:
error C2784: 'class std::mem_fun_t<_R,_Ty> __cdecl std::mem_fun(_R
(__thiscall _Ty::*)(void))' : could not deduce template argument for
'<Unknown>' from 'int (__thiscall X::*)(int)'
If I try some code of my own and use boost::bind instead, I get an error:
error C2780: 'class boost::_bi::bind_t
__cdecl boost::bind(R (__thiscall T::*)(B1,B2 ,B3,B4,B5,B6,B7,B8) const,A1,A2,A3,A4,A5,A6,A7,A8,A9)' : expects 10 arguments - 2 provided
My own code is:
#include "stdafx.h"
#include
[Edward Diener]
Is there any way to use boost::function and member function pointers with VC6 . I realize it is deficient in partial specialization but I was still hoping to be able to use it. All my attempts to compile meet with failure although the compiler tests say that VC6 succeeds both with boost::function and boost::bind.
It works for me :-)
If I try the bind1st.cpp example in libs\function\example directory I get the error:
error C2784: 'class std::mem_fun_t<_R,_Ty> __cdecl std::mem_fun(_R (__thiscall _Ty::*)(void))' : could not deduce template argument for '<Unknown>' from 'int (__thiscall X::*)(int)'
If I try some code of my own and use boost::bind instead, I get an error:
error C2780: 'class boost::_bi::bind_t
,class boost::_bi::list9 __cdecl boost::bind(R (__thiscall T::*)(B1,B2 ,B3,B4,B5,B6,B7,B8) const,A1,A2,A3,A4,A5,A6,A7,A8,A9)' : expects 10 arguments - 2 provided
Amazing. I was struggling with both these very same compiler errors only this morning. Finally I realised I had left something out! Lets have a look at your code and see if you have done the same...
My own code is:
#include "stdafx.h" #include
#include class MyClass { public: int MyMember(int,int,int); };
int MyClass::MyMember(int x,int y,int z) { int a = x + y + z; }
int main(int argc, char* argv[]) { MyClass mcl; boost::function3
bf; bf = boost::bind(&MyClass::MyMember,&mcl); bf(2,3,4); return 0; }
Yep, there it is... you need to tell bind the ordinal positions of each argument to bind to. Just rewrite the line that constructs bind something like this: bf = boost::bind(&MyClass::MyMember,&mcl, _1, _2, _3); ...and it should work. I have not tried to compile the above since I am not on my development machine at the moment, but I'm fairly confident that should do it (or at least point you in the right direction). Regards, [)o IhIL..
"Phil Nash"
[Edward Diener]
Is there any way to use boost::function and member function pointers with VC6 . I realize it is deficient in partial specialization but I was still hoping to be able to use it. All my attempts to compile meet with failure although the compiler tests say that VC6 succeeds both with boost::function and boost::bind.
It works for me :-)
If I try the bind1st.cpp example in libs\function\example directory I get the error:
error C2784: 'class std::mem_fun_t<_R,_Ty> __cdecl std::mem_fun(_R (__thiscall _Ty::*)(void))' : could not deduce template argument for '<Unknown>' from 'int (__thiscall X::*)(int)'
If I try some code of my own and use boost::bind instead, I get an error:
error C2780: 'class boost::_bi::bind_t
,class boost::_bi::list9 __cdecl boost::bind(R (__thiscall T::*)(B1,B2 ,B3,B4,B5,B6,B7,B8) const,A1,A2,A3,A4,A5,A6,A7,A8,A9)' : expects 10 arguments - 2 provided
Amazing. I was struggling with both these very same compiler errors only this morning. Finally I realised I had left something out! Lets have a look at your code and see if you have done the same...
My own code is:
#include "stdafx.h" #include
#include class MyClass { public: int MyMember(int,int,int); };
int MyClass::MyMember(int x,int y,int z) { int a = x + y + z; }
int main(int argc, char* argv[]) { MyClass mcl; boost::function3
bf; bf = boost::bind(&MyClass::MyMember,&mcl); bf(2,3,4); return 0; } Yep, there it is... you need to tell bind the ordinal positions of each argument to bind to. Just rewrite the line that constructs bind something like this:
bf = boost::bind(&MyClass::MyMember,&mcl, _1, _2, _3);
Thanks, that works. I had assumed that if the ordinal positions are not
supplied, that they would just go in order. Evidently ever parameter not
supplied must be given an ordinal position. That makes sense since bind
needs to know how many parameters there are. The documentation is really
deficient in explaining this.
However it doesn't work in VC6 if I change my member function to have 'void'
return and I change my boost::function signature to
boost::function3
Just rewrite the line that constructs bind something like this:
bf = boost::bind(&MyClass::MyMember,&mcl, _1, _2, _3);
Thanks, that works. I had assumed that if the ordinal positions are not supplied, that they would just go in order. Evidently ever parameter not supplied must be given an ordinal position. That makes sense since bind needs to know how many parameters there are. The documentation is really deficient in explaining this.
It does skim over it a bit, but it's there in the examples. Like I said I did it wrong the first time too, but it does make sense as you say.
However it doesn't work in VC6 if I change my member function to have 'void' return and I change my boost::function signature to boost::function3
bf; . Now I get: error C2562: '()' : 'void' function returning a value etc. What a PITA !
Hmmm... I tried your example code (now I have access to my dev machine) and it worked fine for me with a void function. You didn't forget to remove the return statement (probably returning "a") from your method did you? It is true that VC++ 6 doesn't have void returns, but those clever chaps who wrote boost::function worked around it so it works as it should :-) If you definitely did remove your return statement then post the full code again here for further inspection. Regards, [)o IhIL..
It does skim over it a bit, but it's there in the examples. Like I said I did it wrong the first time too, but it does make sense as you say.
However it doesn't work in VC6 if I change my member function to have 'void' return and I change my boost::function signature to boost::function3
bf; . Now I get: error C2562: '()' : 'void' function returning a value etc. What a PITA !
Hmmm... I tried your example code (now I have access to my dev machine) and it worked fine for me with a void function. You didn't forget to remove
"Phil Nash"
return statement (probably returning "a") from your method did you? It is true that VC++ 6 doesn't have void returns, but those clever chaps who wrote boost::function worked around it so it works as it should :-) If you definitely did remove your return statement then post the full code again here for further inspection.
I tried it with Boost 1.28 and it worked but failed in Boost 1.26. Evidently it was fixed between releases. Thanks for your help.
[Edward Diener]
I tried it with Boost 1.28 and it worked but failed in Boost 1.26. Evidently it was fixed between releases. Thanks for your help.
Ah yes. I neglected to ask which release of the boost libraries you were using. I don't know enough about boost::function to be able to say, "ah yes that's because so-and-so was changed", but if it now works for you that is good enough for me :-) Glad I could help, [)o IhIL..
From: "Phil Nash"
#include "stdafx.h" #include
#include class MyClass { public: int MyMember(int,int,int); };
int MyClass::MyMember(int x,int y,int z) { int a = x + y + z; }
int main(int argc, char* argv[]) { MyClass mcl; boost::function3
bf; bf = boost::bind(&MyClass::MyMember,&mcl); bf(2,3,4); return 0; } Yep, there it is... you need to tell bind the ordinal positions of each argument to bind to. Just rewrite the line that constructs bind something like this:
bf = boost::bind(&MyClass::MyMember,&mcl, _1, _2, _3);
...and it should work.
Yes. bind() requires that you supply exactly the number of arguments that is required by the function (object.) http://www.boost.org/libs/bind/bind.html#err_num_args
Please consider updating the documentation so that in the Purpose section
before discussing the use of boost::bind with various types of objects, you
better explain the mechanism regarding argument passing and substitution in
general..
"Peter Dimov"
From: "Phil Nash"
Yep, there it is... you need to tell bind the ordinal positions of each argument to bind to. Just rewrite the line that constructs bind something like this:
bf = boost::bind(&MyClass::MyMember,&mcl, _1, _2, _3);
...and it should work.
Yes. bind() requires that you supply exactly the number of arguments that is required by the function (object.)
From: "Edward Diener"
Please consider updating the documentation so that in the Purpose section before discussing the use of boost::bind with various types of objects, you better explain the mechanism regarding argument passing and substitution in general..
I'll see what I can do, although documentation writing is not one of my top skills. :-) Any specific suggestions?
From: "Edward Diener"
Please consider updating the documentation so that in the Purpose
"Peter Dimov"
before discussing the use of boost::bind with various types of objects, you better explain the mechanism regarding argument passing and substitution in general..
I'll see what I can do, although documentation writing is not one of my top skills. :-) Any specific suggestions?
The suggestion is that you explain how to bind specific arguments to boost::bind, the need to specify placeholders for all the other arguments, and also how to eventually pass arguments for placeholders. I know you are giving various examples when specifying how to use boost::bind with different types of functors, but they don't explain it all in a methodical way. I find the examples good but the general mechanism eluded me when I first read it. I think I understand it now but because it is not explained clearly at the beginning before you give practical examples, it made it much harder to fathom how it all worked. BTW, as a binding mechanism I think it is great work, but I don't think you need even assume that programmers who use it even understand std::bind1st or std::bind2nd if you explain it a bit better. Of course it is your perogative to assume a higher level of understanding of programmers using your boost::bind mechanism and not feel that you have to originally explain it and how it works in a general way.
From: "Edward Diener"
The suggestion is that you explain how to bind specific arguments to boost::bind, the need to specify placeholders for all the other arguments, and also how to eventually pass arguments for placeholders. I know you are giving various examples when specifying how to use boost::bind with different types of functors, but they don't explain it all in a methodical way. I find the examples good but the general mechanism eluded me when I first read it. I think I understand it now but because it is not explained clearly at the beginning before you give practical examples, it made it
much
harder to fathom how it all worked. BTW, as a binding mechanism I think it is great work, but I don't think you need even assume that programmers who use it even understand std::bind1st or std::bind2nd if you explain it a bit better.
This helps, thank you. One more question: it seems that you are using bind() to implement closures. Are you migrating from another closure library, or do you have expectations of how a closure library works, that have got in the way?
"Peter Dimov"
From: "Edward Diener"
The suggestion is that you explain how to bind specific arguments to boost::bind, the need to specify placeholders for all the other
arguments,
and also how to eventually pass arguments for placeholders. I know you are giving various examples when specifying how to use boost::bind with different types of functors, but they don't explain it all in a methodical way. I find the examples good but the general mechanism eluded me when I first read it. I think I understand it now but because it is not explained clearly at the beginning before you give practical examples, it made it much harder to fathom how it all worked. BTW, as a binding mechanism I think it is great work, but I don't think you need even assume that programmers who use it even understand std::bind1st or std::bind2nd if you explain it a bit better.
This helps, thank you. One more question: it seems that you are using bind() to implement closures. Are you migrating from another closure library, or do you have expectations of how a closure library works, that have got in the way?
I am using boost::function to implement closures for a Visual C++ 3rd party library and suggesting boost::bind as the main way to bind member functions to my boost::function implementations. I have even provided some macros which make binding an end user member function to the particular boost::function closures of my classes, using boost::bind, easier. For C++ Builder, as you may know, Borland has a __closure addition to the C++ language, totally non-standard C++, which makes the usage of boost::function and boost::bind unnecessary. Although I am coming from C++ Builder's mechanism, I am very appreciative of the work done with boost::function and boost::bind which makes closures a possibility using pure C++ as it now stands. My expectations have not got in the way once I understood how to use boost::function and boost::bind to implement closures. I find both mechanisms well done even if using a C++ Builder __closure extension is much simpler ( I still like C++ Builder's __closure concept as a possible future native type addition to the C++ language, but that discussion belongs someplace else, probably comp.std.c++ ). It was understanding how boost::bind actually worked which took a while and the fault may well be mine as I restudied bind1st and bind2nd adapters to make sure I knew what was happening there before looking at your documentation on boost::bind again. I admit that I didn't understand intially that when binding one had to supply all the arguments, either in the form of an actual parameter or as a placeholder. That is one of the reasons I suggested that you present a general explanation of the boost::bind mechanism, focusing on what binding is, binding a specific argument, using placeholder arguments, and calling the binding functor with actual values. I know you cover this later in examples for the different uses of boost::bind but I think it would be much more effective if you explain this at the beginning. However I might be unfair in not assuming a greater degree of C++ sophistication in users of Boost and of your implementation.
I am using boost::function to implement closures for a Visual C++ 3rd
From: "Edward Diener"
library and suggesting boost::bind as the main way to bind member functions to my boost::function implementations. I have even provided some macros which make binding an end user member function to the particular boost::function closures of my classes, using boost::bind, easier. For C++ Builder, as you may know, Borland has a __closure addition to the C++ language, totally non-standard C++, which makes the usage of boost::function and boost::bind unnecessary.
Borland __closures are, in some ways, more convenient, but function+bind is a more powerful mechanism. __closures need an exact signature match: void (__closure * event) (int mode, char const * name); class X { void f1(int mode, char const * name); int f2(char const * name, int mode, void * extraData); }; X x; event = &x.f1; // OK event = &x.f2; // error In function+bind terms: function< void, int /*mode (_1)*/, char const * /*name (_2)*/ > event; event = bind(&X::f1, &x /*this*/, _1 /*mode*/, _2 /*name*/); event = bind(&X::f2, &x /*this*/, _2 /*name*/, _1 /*mode*/, 0 /*extraData*/);
"Peter Dimov"
I am using boost::function to implement closures for a Visual C++ 3rd
From: "Edward Diener"
[...] party library and suggesting boost::bind as the main way to bind member functions to my boost::function implementations. I have even provided some macros which make binding an end user member function to the particular boost::function closures of my classes, using boost::bind, easier. For C++ Builder, as you may know, Borland has a __closure addition to the C++ language, totally non-standard C++, which makes the usage of boost::function and boost::bind unnecessary.
Borland __closures are, in some ways, more convenient, but function+bind is a more powerful mechanism. __closures need an exact signature match:
Yes, I am aware of the differences. When I said unnecessary I didn't mean in any way to denigrate boost::function and boost::bind. There is definitely extra functionality in the boost::bind mechanism over C++ Builder __closures if the programmer needs it. And of course the boost mechanisms are C++ and should work on any conforming compiler while C++ Builder's __closure is not pure C++ and only works in C++ Builder. Still, having worked with C++ Builder extensively I have found the C++ Builder __closure to be a wonderfully simple concept which corresponds to something which I have always thought should be part of the C++ language, which is "pointer to member function of any class". But it does no good to argue this idea since both Boost, with boost::function+boost::bind, and Loki, with Loki::Functor, have shown that this concept can be implemented with template mechanisms, and the rejoinder that it can be done via templates will always, I believe, mitigate it being accepted as an addition to the C++ language.
participants (3)
-
Edward Diener
-
Peter Dimov
-
Phil Nash