How to achieve variadic virtual member function

  • A+

So I had this function...

virtual void CallRemoteFunction( const char* pServerGameObjectId, const char* pFunctionName, OVariant arg1 = OVariant(), OVariant arg2 = OVariant(), OVariant arg3 = OVariant(), OVariant arg4 = OVariant(), OVariant arg5 = OVariant(), OVariant arg6 = OVariant(), OVariant arg7 = OVariant(), OVariant arg8 = OVariant(), OVariant arg9 = OVariant() ); 

I decided to rewrite the function because, frankly, I was embarrassed by it. The function is straightforward... take a variable number of arguments of unknown type and do stuff.

I am fairly new to modern C++, so I did some searching and assumed I would find some simple/elegant new way of doing this. I imagined something like...

//hypothetical code virtual void CallRemoteFunction( const char* pServerGameObjectId, const char* pFunctionName, ... args ) {     std::vector<OVariant> argsArray;     for (auto& arg : args )     {         argsArray.push_back(arg)     }      //do other stuff  }  //end hypothetical code 

But in my searches, I could not find anything close. So could anybody kindly give me some ideas on how to refactor my original function into something cleaner or simpler? Note: the solution must be C++ 11 or older.

-Update- The function does not have to be virtual.
I want to be able to call the function like so...


Here is the implementation for reference

//calls function on client if this peer is a linked server or vice versa void Peer::CallRemoteFunction( const char* pServerGameObjectId,  const char*  pFunctionName, OVariant arg1, OVariant arg2, OVariant arg3, OVariant arg4,  OVariant arg5, OVariant arg6, OVariant arg7, OVariant arg8, OVariant arg9 ) {     Command command;     command.SetObjectName( pServerGameObjectId );     command.SetFunctionName( pFunctionName );     command.ResetArgs();     if ( arg1.IsValid() ){ command.PushArg( arg1 ); }     if ( arg2.IsValid() ){ command.PushArg( arg2 ); }     if ( arg3.IsValid() ){ command.PushArg( arg3 ); }     if ( arg4.IsValid() ){ command.PushArg( arg4 ); }     if ( arg5.IsValid() ){ command.PushArg( arg5 ); }     if ( arg6.IsValid() ){ command.PushArg( arg6 ); }     if ( arg7.IsValid() ){ command.PushArg( arg7 ); }     if ( arg8.IsValid() ){ command.PushArg( arg8 ); }     if ( arg9.IsValid() ){ command.PushArg( arg9 ); }      LOG_DEBUG( "Calling Remote Function : " << pServerGameObjectId << "." <<  command.GetFunctionName() );     ByteArray buffer( command.GetSerializeSize() );     command.Serialize( buffer );      ZMQMessage* request = new ZMQMessage();//deleted when sent via zmq     request->addmem( buffer.GetBytes(), buffer.m_NumBytes );      PushMessage( MDPW_REQUEST, m_pServiceId, request ); } 

Sure, you can have that, if you want. You just have to combine a templated forwarder with a non-templated virtual function:

virtual void DoCallRemoteFunction(     const char* pServerGameObjectId,     const char* pFunctionName,     std::initializer_list<OVariant> args ) {     ... }  template<class... ARGS> void CallRemoteFunction(     const char* pServerGameObjectId,     const char* pFunctionName,     ARGS&&... args ) {     DoCallRemoteFunction(         pServerGameObjectId,         pFunctionName,         {OVariant{std::forward<ARGS>(args)}...}); } 

I have given them different names because you presumably will override the virtual function, and probably don't want the API-function to be shadowed then.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: