Using boost function with virtual methods

Hi, I have a simple inheritance: class A {}; class RegressionTestScenario; typedef A CurveGen; typedef boost::shared_ptr<CurveGen> CurveGenPtr; typedef boost::function<void (RegressionTestScenario*, const std::string &)> actionFuntion; typedef boost::shared_ptr<actionFuntion> actionFuntionPtr; class RegressionTestScenario { public: virtual ~RegressionTestScenario() {} virtual void doScenario() = 0; virtual boost::shared_ptr<std::string> fileName() const = 0; virtual boost::shared_ptr<std::string> print() const = 0; virtual void unwrapPackage(const std::string &contents) = 0; protected: typedef std::vector<std::pair<actionFuntionPtr, std::string> > actionCollection; actionCollection m_actionCollection; }; class CurveGenRegressionTestScenario : public RegressionTestScenario { public: virtual void doScenario(); virtual boost::shared_ptr<std::string> fileName() const; virtual boost::shared_ptr<std::string> print() const; virtual void unwrapPackage(const std::string &contents); private: CurveGenPtr m_curveGenPtr; void addAction(const std::string &action); void changeBaseDate(const std::string &argument); void changeStvParameter(const std::string &argument); void changeLtvParameter(const std::string &argument); void changeHalfLife(const std::string &argument); void changeParameterSet(const std::string &argument); void changeCurrencyCouple(const std::string &argument); }; and I am trying to use the following: actionFuntion funPtr; if(params[0]=="BaseDate") funPtr = &CurveGenRegressionTestScenario::changeBaseDate; but it fails. I have no idea why. Could someone give me a hint? This is the output from the compiler: Cheers 1>------ Build started: Project: compare, Configuration: Release Win32 ------ 1>Compiling... 1>RegressionTestMain.cpp 1>D:\Dev\SOHO_NEW\Thirdparty\boost/bind/mem_fn_template.hpp(156) : error C2440: 'newline' : cannot convert from 'RegressionTestScenario *' to 'CurveGenRegressionTestScenario *' 1> Cast from base to derived requires dynamic_cast or static_cast 1> D:\Dev\SOHO_NEW\Thirdparty\boost/bind/mem_fn_template.hpp(171) : see reference to function template instantiation 'R boost::_mfi::mf1<R,T,A1>::call<U,const std::string>(U &,const void *,B1 &) const' being compiled 1> with 1> [ 1> R=void, 1> T=CurveGenRegressionTestScenario, 1> A1=const std::string &, 1> U=RegressionTestScenario *, 1> B1=const std::string 1> ] 1> D:\Dev\SOHO_NEW\Thirdparty\boost/function/function_template.hpp(225) : see reference to function template instantiation 'R boost::_mfi::mf1<R,T,A1>::operator ()<T0>(U &,A1) const' being compiled 1> with 1> [ 1> R=void, 1> T=CurveGenRegressionTestScenario, 1> A1=const std::string &, 1> T0=RegressionTestScenario *, 1> U=RegressionTestScenario * 1> ] 1> D:\Dev\SOHO_NEW\Thirdparty\boost/function/function_template.hpp(222) : while compiling class template member function 'void boost::detail::function::function_void_mem_invoker2<MemberPtr,R,T0,T1>::invoke(boost::detail::function::function_buffer &,T0,T1)' 1> with 1> [ 1> MemberPtr=void (__thiscall CurveGenRegressionTestScenario::* )(const std::string &), 1> R=void, 1> T0=RegressionTestScenario *, 1> T1=const std::basic_string<char,std::char_traits<char>,std::allocator<char>> & 1> ] 1> D:\Dev\SOHO_NEW\Thirdparty\boost/function/function_template.hpp(913) : see reference to class template instantiation 'boost::detail::function::function_void_mem_invoker2<MemberPtr,R,T0,T1>' being compiled 1> with 1> [ 1> MemberPtr=void (__thiscall CurveGenRegressionTestScenario::* )(const std::string &), 1> R=void, 1> T0=RegressionTestScenario *, 1> T1=const std::basic_string<char,std::char_traits<char>,std::allocator<char>> & 1> ] 1> D:\Dev\SOHO_NEW\Thirdparty\boost/function/function_template.hpp(722) : see reference to function template instantiation 'void boost::function2<R,T0,T1>::assign_to<Functor>(Functor)' being compiled 1> with 1> [ 1> R=void, 1> T0=RegressionTestScenario *, 1> T1=const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &, 1> Functor=void (__thiscall CurveGenRegressionTestScenario::* )(const std::string &) 1> ] 1> D:\Dev\SOHO_NEW\Thirdparty\boost/function/function_template.hpp(1065) : see reference to function template instantiation 'boost::function2<R,T0,T1>::function2<void(__thiscall CurveGenRegressionTestScenario::* )(const std::string &)>(Functor,int)' being compiled 1> with 1> [ 1> R=void, 1> T0=RegressionTestScenario *, 1> T1=const std::basic_string<char,std::char_traits<char>,std::allocator<char>> &, 1> Functor=void (__thiscall CurveGenRegressionTestScenario::* )(const std::string &) 1> ] 1> D:\Dev\SOHO_NEW\Thirdparty\boost/function/function_template.hpp(1105) : see reference to function template instantiation 'boost::function<Signature>::function<void(__thiscall CurveGenRegressionTestScenario::* )(const std::string &)>(Functor,int)' being compiled 1> with 1> [ 1> Signature=void (RegressionTestScenario *,const std::string &), 1> Functor=void (__thiscall CurveGenRegressionTestScenario::* )(const std::string &) 1> ] 1> .\RegressionTestMain.cpp(182) : see reference to function template instantiation 'boost::function<Signature> &boost::function<Signature>::operator =<void(__thiscall CurveGenRegressionTestScenario::* )(const std::string &)>(Functor)' being compiled 1> with 1> [ 1> Signature=void (RegressionTestScenario *,const std::string &), 1> Functor=void (__thiscall CurveGenRegressionTestScenario::* )(const std::string &) 1> ] 1>D:\Dev\SOHO_NEW\Thirdparty\boost/bind/mem_fn_template.hpp(156) : error C2647: '->*' : cannot dereference a 'void (__thiscall CurveGenRegressionTestScenario::* const )(A1)' on a 'RegressionTestScenario *' 1> with 1> [ 1> A1=const std::string & 1> ] 1>Build log was saved at "file://d:\Dev\OwnProgs\compare\compare\Release\BuildLog.htm" 1>compare - 2 error(s), 0 warning(s) ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== ___________________________________________________________ This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and delete this e-mail. Any unauthorised copying, disclosure or distribution of the material in this e-mail is prohibited. Please refer to http://www.bnpparibas.co.uk/en/information/legal_information.asp?Code=ECAS-8... for additional disclosures.

On Fri, Jul 1, 2011 at 1:06 PM, <przemyslaw.sliwa@uk.bnpparibas.com> wrote:
I have a simple inheritance:
class RegressionTestScenario;
typedef boost::function<void (RegressionTestScenario*, const std::string &)> actionFuntion;
class RegressionTestScenario { public: virtual ~RegressionTestScenario() {} };
class CurveGenRegressionTestScenario : public RegressionTestScenario { public: void changeBaseDate(const std::string &argument); };
and I am trying to use the following:
actionFuntion funPtr; funPtr = &CurveGenRegressionTestScenario::changeBaseDate;
but it fails. I have no idea why. Could someone give me a hint?
The inheritance is going the wrong way. An actionFuntion instance might be called with any RegressionTestScenario*. But you can't call a CurveGenRegressionTestScenario method with any old RegressionTestScenario* -- only a RegressionTestScenario* that is also a CurveGenRegressionTestScenario* would be valid. The compiler isn't going to synthesize logic for you to dynamic_cast<CurveGenRegressionTestScenario&>(*your_first_param) (which throws unless your_first_param is in fact a CurveGenRegressionTestScenario*). If you want such logic, you'll have to code an adapter and store that.

The inheritance is going the wrong way. An actionFuntion instance might be called with any RegressionTestScenario*. But you can't call a CurveGenRegressionTestScenario method with any old RegressionTestScenario* -- only a RegressionTestScenario* that is also a CurveGenRegressionTestScenario* would be valid. The compiler isn't going to synthesize logic for you to dynamic_cast<CurveGenRegressionTestScenario&>(*your_first_param) (which throws unless your_first_param is in fact a CurveGenRegressionTestScenario*). If you want such logic, you'll have to code an adapter and store that.
It has nothing to do with inheritance. The following code won't compile as well: struct A { void f(int i); }; boost::function<void(A *, int)> func = &A::f;

On 7/2/11 1:25 PM, Igor R wrote:
The inheritance is going the wrong way. An actionFuntion instance might be called with any RegressionTestScenario*. But you can't call a CurveGenRegressionTestScenario method with any old RegressionTestScenario* -- only a RegressionTestScenario* that is also a CurveGenRegressionTestScenario* would be valid. The compiler isn't going to synthesize logic for you to dynamic_cast<CurveGenRegressionTestScenario&>(*your_first_param) (which throws unless your_first_param is in fact a CurveGenRegressionTestScenario*). If you want such logic, you'll have to code an adapter and store that. It has nothing to do with inheritance. The following code won't compile as well:
struct A { void f(int i); };
boost::function<void(A *, int)> func = &A::f;
Note that func = $A::f does not have the same signature a &g where g is defined as void g(A*, int); It may act in an analogous manner, but the language does not make them the same. I have seen some systems were the calling convention even put the A* in a different register for the two calls. -- Richard Damon

typedef boost::function<void (RegressionTestScenario*, const std::string &)> actionFuntion; typedef boost::shared_ptr<actionFuntion> actionFuntionPtr; <...> class CurveGenRegressionTestScenario : public RegressionTestScenario { public: void changeBaseDate(const std::string &argument); <...> and I am trying to use the following:
actionFuntion funPtr; funPtr = &CurveGenRegressionTestScenario::changeBaseDate;
but it fails. I have no idea why. Could someone give me a hint?
boost::function<void (RegressionTestScenario*, const std::string &)> -- is a callable with 2 arguments. &CurveGenRegressionTestScenario::changeBaseDate -- is a ptr to a member function. These 2 types are incompatible. You probably should look at Boost.Bind to accomplish your task: http://www.boost.org/doc/libs/1_46_1/libs/bind/bind.html#with_member_pointer...

On Sat, Jul 2, 2011 at 1:21 PM, Igor R <boost.lists@gmail.com> wrote:
typedef boost::function<void (RegressionTestScenario*, const std::string &)> actionFuntion; typedef boost::shared_ptr<actionFuntion> actionFuntionPtr; <...> class CurveGenRegressionTestScenario : public RegressionTestScenario { public: void changeBaseDate(const std::string &argument); <...> and I am trying to use the following:
actionFuntion funPtr; funPtr = &CurveGenRegressionTestScenario::changeBaseDate;
but it fails. I have no idea why. Could someone give me a hint?
boost::function<void (RegressionTestScenario*, const std::string &)> -- is a callable with 2 arguments. &CurveGenRegressionTestScenario::changeBaseDate -- is a ptr to a member function. These 2 types are incompatible. You probably should look at Boost.Bind to accomplish your task: http://www.boost.org/doc/libs/1_46_1/libs/bind/bind.html#with_member_pointer...
I was going to suggest boost::bind(), but when I put the trimmed-down code above into a source file, changed it to a boost::bind() expression and tried to compile it with g++, it complained about the type incompatibility. So there are two different problems, one of which is inheritance.
participants (4)
-
Igor R
-
Nat Linden
-
przemyslaw.sliwa@uk.bnpparibas.com
-
Richard Damon