return type of bind object
Dear People, I have defined a function as follows. double accept_prob_fn(const double x, const double be, const double theta, const double a, const double b); Now, I define the temporary function object bind(accept_prob_fn, _1, be, theta, a, b); So this function object would return the first argument, x. However, I want to save this function object to a function object called foo, say. So I want to do something like Type foo = bind(accept_prob_fn, _1, be, theta, a, b); However, the problem I have is that I'm not sure what type foo should be. I forced an error with my compiler (to try to see what it thought the type of the rhs should be) by using Type as double, but all I got was brent.cc:9: cannot convert `boost::_bi::bind_t<double, double (*)(double, double, double, double, double), boost::_bi::list5<boost::arg<1>, boost::_bi::value<double>, boost::_bi::value<double>, boost::_bi::value<double>, boost::_bi::value<double> > >' to `double' in initialization Eww. I've tried looking at the documentation, but I find it pretty much incomprehensible. Could someone a) Tell me what "Type" should be. b) Give me some brief indication of the reasoning by which one might arrive at this conclusion, with appropriate references to the documentation? Thanks. Feel free to cc a copy of any reply to me. I'll check the mailing list via gmane in any case. Faheem.
On Friday 14 March 2003 09:45 pm, Faheem Mitha wrote:
Dear People,
I have defined a function as follows.
double accept_prob_fn(const double x, const double be, const double theta, const double a, const double b);
Now, I define the temporary function object
bind(accept_prob_fn, _1, be, theta, a, b);
So this function object would return the first argument, x. However, I want to save this function object to a function object called foo, say.
So I want to do something like
Type foo = bind(accept_prob_fn, _1, be, theta, a, b);
However, the problem I have is that I'm not sure what type foo should be. I forced an error with my compiler (to try to see what it thought the type of the rhs should be) by using Type as double, but all I got was
brent.cc:9: cannot convert `boost::_bi::bind_t<double, double (*)(double, double, double, double, double), boost::_bi::list5<boost::arg<1>, boost::_bi::value<double>, boost::_bi::value<double>, boost::_bi::value<double>, boost::_bi::value<double> > >' to `double' in initialization
Eww.
I've tried looking at the documentation, but I find it pretty much incomprehensible. Could someone
a) Tell me what "Type" should be.
The type is "unspecified", may vary from compiler to compiler, and is hideous on every compiler. For these reasons, it's intentional that you can't name the type directly (see http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1438.htm, section IIIB). However, you can include <boost/function.hpp> and make the Type: boost::function<double(double x)> (or, if your compiler isn't up to par, boost::function1<double, double>). See the Boost.Function documentation for more information about the Function library. Doug
Hi ! I was using boost:function for a while now with success on Visual C 7.0 ( MSVC 1300 ) . I was always using the most actual boost 1.30.0 version from the CVS. Today i updated the CVS again ( after two days of not doing so ) and suddenly my code which relied on boost::function does not compile anymore. I think there have some changes been made, so i need to change my code, but since there is no boost::function documentation in the CVS yet can someone please enlighten me what has changed .. ? Here is the relevant code: ( I have marked the line where compilation fails and provided the exact error details below ) ( This code compiled perfectly two days ago ) Header: #include <boost/any.hpp> #include <boost/function.hpp> #include <boost/intrusive_ptr.hpp> #include "..\Platform\Config.h" #include "IType.h" namespace Fr { namespace Core { namespace Reflection { /// Function type for conversions. /// Converts value from and stores the result in the target. typedef boost::function1< boost::any,boost::any > ConversionFunction; FR_CORE_API void RegisterConversion( ConversionFunction,const IType &,const IType & ); FR_CORE_API ConversionFunction * FindConversion( const IType &,const IType & ); FR_CORE_API boost::any Convert( const boost::any &,const IType & ); FR_CORE_API boost::any Convert( const boost::any &,const boost::any &); } } } IMplementation: / Disable performance warning #include "..\Platform\Config.h" #include <vector> #include <boost/lexical_cast.hpp> #include "IConverter.h" #include "..\Debug\Exception.h" using namespace Fr::Core::Reflection; struct ConversionInfo { ConversionFunction function; const IType * from; const IType * to; }; std::vector< ConversionInfo > sConversions; void Fr::Core::Reflection::RegisterConversion( ConversionFunction func,const IType & from,const IType & to ) { for ( unsigned i = 0; i < sConversions.size(); i++ ) { if ( *sConversions[i].to == to && *sConversions[i].from == from ) return; } // Else add ConversionInfo info; info.function = func; info.from = &from; info.to = &to; // Store sConversions.push_back( info ); } ConversionFunction * Fr::Core::Reflection::FindConversion( const IType &from,const IType &to ) { // No conversion same type. if ( from == to ) return NULL; for ( unsigned int i = 0; i < sConversions.size(); i++ ) { // Check if ( *sConversions[i].from == from && *sConversions[i].to == to ) return &sConversions[i].function; } return NULL; } boost::any Fr::Core::Reflection::Convert( const boost::any &from,const IType & to ) { // First we try to get the type from the input data. const IType & fromType = GetType( ConvertCppTypename(from.type().name()) ); // Check if it worked if ( fromType != NullType() ) { if ( fromType == to ) return from; // Try to find conversion. ConversionFunction * func = FindConversion( fromType,to ); // If we have one if ( func ) { ConversionFunction convFunc = *func; return convFunc( from ); } else { std::string msg = "Unable to find conversion from: "; msg += fromType.GetName(); msg += " to: "; msg += to.GetName(); Throw(msg); } } else { std::string msg = "Unable to retrieve type descriptor for data type: "; msg += from.type().name(); Throw( msg ); } return from; } boost::any Fr::Core::Reflection::Convert( const boost::any &from,const boost::any & to ) { // First we try to get the type from the input data. const IType & fromType = GetType( ConvertCppTypename(from.type().name()) ); const IType & toType = GetType( ConvertCppTypename(to.type().name()) ); // Check if it worked if ( fromType != NullType() && toType != NullType() ) { if ( fromType == toType ) return from; if ( FindConversion( fromType,toType ) ) { return Convert( from,toType ); } return to; } else { return to; } return to; } // ----------------------------------------------------------------------------- // Standard conversions // ----------------------------------------------------------------------------- static boost::any StringToFloat( const boost::any & input ) { std::string data = boost::any_cast<std::string> ( input ); return boost::lexical_cast<float>(data); } static boost::any FloatToString( const boost::any & input ) { float data = boost::any_cast<float> ( input ); return std::string("0"); } static boost::any StringToInt( const boost::any & input ) { std::string data = boost::any_cast<std::string> ( input ); return boost::lexical_cast<int>(data); } static boost::any IntToString( const boost::any & input ) { int data = boost::any_cast<int> ( input ); return std::string("0"); } #include "..\Math\Vector3.h" static boost::any StringToVec3f( const boost::any & input ) { std::string data = boost::any_cast<std::string> ( input ); Vec3f result; sscanf( data.c_str(),"%f;%f;%f",&result.x,&result.y,&result.z); return result; } static boost::any Vec3fToString( const boost::any & input ) { Vec3f data = boost::any_cast<Vec3f> ( input ); std::string result; //result += boost::lexical_cast<std::string> ( data.x ); result += ";"; //result += boost::lexical_cast<std::string> ( data.y ); result += ";"; //result += boost::lexical_cast<std::string> ( data.z ); return result; } static boost::any BoolToString( const boost::any & input ) { bool data = boost::any_cast<bool> ( input ); if ( data ) return std::string("True"); else return std::string("False"); } static boost::any StringToBool( const boost::any & input ) { std::string data = boost::any_cast<std::string> ( input ); if ( data == "True" || data == "true" || data == "TRUE" || data == "On" || data == "on" || data == "ON" ) return true; else return false; } // ----------------------------------------------------------------------------- // Automatic conversion registration // ----------------------------------------------------------------------------- void RegisterStandardConversions() { ///////////////////////////////////////////////////////////////////////////////// // HERE COMPILIATION FAILS: ( Following line ) //////////////////////////////////////////////////////////////////////////// ConversionFunction stf = &StringToFloat; /////////////////////////////////////////////////////////////////////////////////// /// VISUAL C ERROR OUTPUT: ////////////////////////////////////////////////////////////////////////////////// D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2510: 'value' : left of '::' must be a class/struct/union D:\Sdk\boost\boost\type_traits\is_class.hpp(94) : see reference to class template instantiation 'boost::detail::is_class_impl<T>' being compiled with [ T=boost::any (__cdecl *)(const boost::any &) ] D:\Sdk\boost\boost\type_traits\is_stateless.hpp(31) : see reference to class template instantiation 'boost::is_class<T>' being compiled with [ T=boost::any (__cdecl *)(const boost::any &) ] D:\Sdk\boost\boost\type_traits\is_stateless.hpp(43) : see reference to class template instantiation 'boost::detail::is_stateless_impl<T>' being compiled with [ T=boost::any (__cdecl *)(const boost::any &) ] D:\Sdk\boost\boost\function\function_base.hpp(193) : see reference to class template instantiation 'boost::is_stateless<T>' being compiled with [ T=boost::any (__cdecl *)(const boost::any &) ] D:\Sdk\boost\boost\function\function_template.hpp(431) : see reference to class template instantiation 'boost::detail::function::get_function_tag<F>' being compiled with [ F=boost::any (__cdecl *)(const boost::any &) ] D:\Sdk\boost\boost\function\function_template.hpp(293) : see reference to function template instantiation 'void boost::function1<R,T0,Allocator>::assign_to(Functor)' being compiled with [ R=boost::any, T0=boost::any, Allocator=int, Functor=boost::any (__cdecl *)(const boost::any &) ] \Work\FakedReality\Source\Core\Reflection\IConverter.cpp(214) : see reference to function template instantiation 'boost::function1<R,T0,Allocator>::function1(const Functor & )' being compiled with [ R=boost::any, T0=boost::any, Allocator=int, Functor=boost::any (__cdecl *)(const boost::any &) ] D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2065: 'ice_not' : undeclared identifier D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2679: binary '<' : no operator found which takes a right-hand operand of type '' (or there is no acceptable conversion) D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2955: 'boost::type_traits::ice_and' : use of class template requires template argument list D:\Sdk\boost\boost\type_traits\detail\ice_and.hpp(25) : see declaration of 'boost::type_traits::ice_and' D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2955: 'boost::type_traits::ice_and' : use of class template requires template argument list D:\Sdk\boost\boost\type_traits\detail\ice_and.hpp(25) : see declaration of 'boost::type_traits::ice_and' D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2039: 'value' : is not a member of 'operator``global namespace''' D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2065: 'value' : undeclared identifier D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2676: binary '>' : '' does not define this operator or a conversion to a type acceptable to the predefined operator D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2056: illegal expression ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RegisterConversion( stf,typeof<std::string>(),typeof<float>() ); ConversionFunction fts = &FloatToString; RegisterConversion( fts,typeof<float>(),typeof<std::string>() ); ConversionFunction its = &IntToString; RegisterConversion( its,typeof<int>(),typeof<std::string>() ); ConversionFunction sti = &StringToInt; RegisterConversion( sti,typeof<std::string>(),typeof<int>() ); ConversionFunction v3fts = &Vec3fToString; RegisterConversion( v3fts,typeof<Vec3f>(),typeof<std::string>() ); ConversionFunction stv3f = &StringToVec3f; RegisterConversion( stv3f,typeof<std::string>(),typeof<Vec3f>() ); ConversionFunction stb = &StringToBool; RegisterConversion( stb,typeof<std::string>(),typeof<bool> () ); ConversionFunction bts = &BoolToString; RegisterConversion( bts,typeof<bool>(),typeof<std::string>()); } ////////////////////// SECOND Problem As you may note all conversions from data types to std::string are commented out ! This is because boost::lexical_cast fails to compile in DEBUG mode ( it compiles fine in RELEASE Mode and also works like a charm in RELEASE mode ) Thanks for your time Bernhard Glück
John, This regression in Function is coming from your recently change to is_class.hpp. Would you mind taking a look? On Saturday 15 March 2003 01:31 pm, Bernhard Glueck wrote:
Hi !
I was using boost:function for a while now with success on Visual C 7.0 ( MSVC 1300 ) .
I was always using the most actual boost 1.30.0 version from the CVS. Today i updated the CVS again ( after two days of not doing so ) and suddenly my code which relied on boost::function does not compile anymore.
boost::function hasn't changed in the last few weeks, but some of the libraries it depends on have changed.
I think there have some changes been made, so i need to change my code, but since there is no boost::function documentation in the CVS yet can someone please enlighten me what has changed .. ?
FYI, updated documentation for Boost.Function is here: http://www.cs.rpi.edu/~gregod/boost/doc/html/function.html Also, it's on the RC_1_30_0 branch in CVS (that will be 1.30.0; mainline CVS is for 1.31.0 and later).
Here is the relevant code: ( I have marked the line where compilation fails and provided the exact error details below ) ( This code compiled perfectly two days ago ) [snip code] /////////////////////////////////////////////////////////////////////////// //////// /// VISUAL C ERROR OUTPUT: /////////////////////////////////////////////////////////////////////////// /////// D:\Sdk\boost\boost\type_traits\is_class.hpp(78) : error C2510: 'value' : left of '::' must be a class/struct/union D:\Sdk\boost\boost\type_traits\is_class.hpp(94) : see reference to class template instantiation 'boost::detail::is_class_impl<T>' being compiled with [ T=boost::any (__cdecl *)(const boost::any &) ]
Looks like a type_traits problem. I suspect this patch: Index: is_class.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/type_traits/is_class.hpp,v retrieving revision 1.5 retrieving revision 1.6 diff -r1.5 -r1.6 84a85
::boost::type_traits::ice_not< ::boost::is_function<T>::value ::value
John?
////////////////////// SECOND Problem As you may note all conversions from data types to std::string are commented out ! This is because boost::lexical_cast fails to compile in DEBUG mode ( it compiles fine in RELEASE Mode and also works like a charm in RELEASE mode )
The implementation of lexical_cast w.r.t. strings is in a state of flux. I'm too far out of the loop to be helpful on this one. Doug
[ ... ]
Index: is_class.hpp =================================================================== RCS file: /cvsroot/boost/boost/boost/type_traits/is_class.hpp,v retrieving revision 1.5 retrieving revision 1.6 diff -r1.5 -r1.6 84a85
::boost::type_traits::ice_not< ::boost::is_function<T>::value ::value
John?
This is due to the missing comma I reported in http://lists.boost.org/MailArchives/boost/msg45211.php Regards, Andreas
From: "Bernhard Glueck" <bernhard@realspace.org>
////////////////////// SECOND Problem As you may note all conversions from data types to std::string are commented out ! This is because boost::lexical_cast fails to compile in DEBUG mode ( it compiles fine in RELEASE Mode and also works like a charm in RELEASE mode )
Could you have given the error messages it gives, when these are uncommented? Regards, Terje
Terje Slettebø wrote:
From: "Bernhard Glueck" <bernhard@realspace.org>
////////////////////// SECOND Problem As you may note all conversions from data types to std::string are commented out ! This is because boost::lexical_cast fails to compile in DEBUG mode ( it compiles fine in RELEASE Mode and also works like a charm in RELEASE mode )
Could you have given the error messages it gives, when these are uncommented?
Regards,
Terje
Info: <http://www.boost.org> Wiki: <http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl> Unsubscribe: <mailto:boost-users-unsubscribe@yahoogroups.com>
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
I will as soon as the other problem is solved ( right now the compiler breaks the build before coming to the uncommented std:.string conversions ) Also note that the lexical cast interface is not a real "showstopper" issue ... since it would not break an external interface... just the first problem about boost::function is really severe.
On Sat, 15 Mar 2003 12:22:34 -0500, Douglas Gregor <gregod@cs.rpi.edu> wrote:
On Friday 14 March 2003 09:45 pm, Faheem Mitha wrote:
Dear People,
I have defined a function as follows.
double accept_prob_fn(const double x, const double be, const double theta, const double a, const double b);
Now, I define the temporary function object
bind(accept_prob_fn, _1, be, theta, a, b);
So this function object would return the first argument, x. However, I want to save this function object to a function object called foo, say.
So I want to do something like
Type foo = bind(accept_prob_fn, _1, be, theta, a, b);
However, the problem I have is that I'm not sure what type foo should be. [snip]
The type is "unspecified", may vary from compiler to compiler, and is hideous on every compiler. For these reasons, it's intentional that you can't name the type directly (see http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1438.htm, section IIIB).
However, you can include <boost/function.hpp> and make the Type: boost::function<double(double x)>
(or, if your compiler isn't up to par, boost::function1<double, double>). See the Boost.Function documentation for more information about the Function library.
Thanks, this is very helpful. boost::function<double(double x)> works fine with gcc 3.0. Nice simple syntax; takes a double argument and returns a double. A small comment. The paper you quote above (http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1438.htm) does clearly state that the return type is unspecified, but does not say anything further (as far as I can see) about how to handle assignments like above, and it is presumably not part of the official documentation anyway. Also, the bind documentation itself (again, as far as I can see) does not say anything about how to handle assignments. Therefore, would it not be a good idea to include an example in the bind documentation showing how assignments should be handled? In any case, more and varied examples are always a good thing. Bear in mind I don't have much C++ experience, so the needed syntax may have been quite clear to a more experienced person. Thanks again for your help. Faheem.
On Tuesday 18 March 2003 10:50 pm, Faheem Mitha wrote:
A small comment. The paper you quote above (http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1438.htm) does clearly state that the return type is unspecified, but does not say anything further (as far as I can see) about how to handle assignments like above, and it is presumably not part of the official documentation anyway.
There is one example (just before section II) in the proposal, but because Bind and Function are completely separate libraries (with separate proposals), the proposal does not expand on the example.
Also, the bind documentation itself (again, as far as I can see) does not say anything about how to handle assignments. Therefore, would it not be a good idea to include an example in the bind documentation showing how assignments should be handled? In any case, more and varied examples are always a good thing.
There is an example of using the two libraries together here: http://www.boost.org/libs/bind/bind.html#with_boost_function but perhaps we need something that says "if you want to store a bind object, use Function" instead of "if you want to use Function with bind, you can do this (storing a bind object)". Doug
On Wed, 19 Mar 2003 10:43:17 -0500, Douglas Gregor <gregod@cs.rpi.edu> wrote:
On Tuesday 18 March 2003 10:50 pm, Faheem Mitha wrote:
Also, the bind documentation itself (again, as far as I can see) does not say anything about how to handle assignments. Therefore, would it not be a good idea to include an example in the bind documentation showing how assignments should be handled? In any case, more and varied examples are always a good thing.
There is an example of using the two libraries together here: http://www.boost.org/libs/bind/bind.html#with_boost_function but perhaps we need something that says "if you want to store a bind object, use Function" instead of "if you want to use Function with bind, you can do this (storing a bind object)".
Right. I saw the example you mentioned, but the significance (and utility) completely passed me by, partly, perhaps, because it was inside a class, and also because it was not stated explicitly that this was how you stored boost objects. It would also be good to use an example with several arguments. As someone who has done a lot of teaching, I know it is best to keep examples as simple as possible, while still having the features necessary to serve its purpose. A lot of free software libraries have the problem that they give examples that are way too complicated, and include lots of irrelevant stuff, which just causes confusion. Your documentation is pretty good, actually. I think it would be good if it was stated explicitly that 1) The return type of Bind objects is undefined (or whatever). 2) If you want to store a bind object, use boost::function, with a pointer to the appropriate section. An example with several arguments would be nice. Of course, finding the documentation once they have been told (1) and (2) is the easy part. I can attest personally that expecting people to read between the lines (if they are not experts) will not work well in this case. My apologies if it sounds like I am lecturing you. I am very grateful for your helpful feedback. Faheem.
participants (5)
-
Andreas Huber
-
Bernhard Glueck
-
Douglas Gregor
-
Faheem Mitha
-
Terje Slettebø