Как добиться вариативной функции виртуального члена - PullRequest
0 голосов
/ 13 мая 2018

Так у меня была эта функция ...

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

Я решил переписать функцию, потому что, честно говоря, меня это смутило. Функция проста ... взять переменное число аргументов неизвестного типа и делать вещи.

Я довольно новичок в современном C ++, поэтому я немного поискал и предположил, что найду какой-нибудь простой / элегантный новый способ сделать это. Я представил что-то вроде ...

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

Но в своих поисках я не мог найти ничего близкого. Так может кто-нибудь любезно дать мне несколько идей о том, как преобразовать мою первоначальную функцию во что-то более чистое или простое? Примечание: решение должно быть C ++ 11 или старше.

-Update- Функция не должна быть виртуальной.
Я хочу, чтобы иметь возможность вызывать функцию так ...

CallRemoteFunction("serverID","someFunc",1,2,3);

Вот реализация для справки

//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 );
}

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Конечно, вы можете иметь это, если хотите.Вам просто нужно объединить шаблонный экспедитор с не шаблонной виртуальной функцией.

Я использую gsl::span (" Что такое" span "и когда мне следует его использовать? ") и автоматический std::array ( не нативный, чтобы избежать особого случая 0) для лучшей универсальности, стабильности и эффективности.

virtual void DoCallRemoteFunction(
    const char* pServerGameObjectId,
    const char* pFunctionName,
    gsl::span<OVariant> args
) {
    ...
}

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

Я дал им разные имена, потому что вы, вероятно, переопределите виртуальную функцию и, возможно, не хотите, чтобы API-функция затемнялась.

0 голосов
/ 13 мая 2018

Если вы готовы принять немного другой синтаксис вызова (например, std::max также использует ), вы можете найти очень элегантное решение:

virtual void CallRemoteFunction( const char* pServerGameObjectId, const char* pFunctionName, std::initializer_list<QVariant> args )
{
    std::vector<OVariant> argsArray;
    for (auto& arg : args )
    {
        argsArray.push_back(arg)
    }

    //do other stuff
}

Называется так:

CallRemoteFunction("foo", "bar", { arg1, arg2, arg3 });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...