c++11parametersparameter-passingusing-declarationtemplate-aliases

passing a parameter pack over a legacy function signature using forward_as_tuple


In my app I would like to pass in a parameter pack over a legacy function signature, and change the values. Here is code that illustrates my question with my attempts as comments:

#include <tuple>
#include <cassert>

void LegacySignature( void* param );

template< typename... ArgsT >
// using ???; // attempt: can 'template alias' or 'using declaration' make the pack's type visible so I can use it inside the LegacyFunction?
void MyFunc( ArgsT&... args )
{
  auto userArgsTuple = std::forward_as_tuple< ArgsT&... >( args... );

  LegacySignature( &userArgsTuple );
}

void LegacySignature( void* param )
{
//  auto userArgsTuple = reinterpret_cast<???>( param ); // attempt: how can I get the parameter pack's type declared so I can use it here?

  // do something with the params like change num to 44 and tf to true;
  //userArgsTuple->num = 44; // desired functionality
  //userArgsTuple->tf = true; // desired functionality
}

int main()
{
  int num { 33 };
  bool tf { false };
  MyFunc( num, tf );
  assert( num == 44 && tf == true );

  return 0;
}

Is there a way to make the parameter pack a declarable lvalue?


Solution

  • The code below fixes the sample code so that it answers the question as to how to pass a parameter pack over a legacy function signature using forward_as_tuple.

    #include <tuple>
    #include <cassert>
    #include <memory>
    #include <functional>
    
    #define ARGSET int, bool
    
    void LegacySignature( long* param ); // ie, LPARAM
    
    template< typename... ArgsT >
    struct MyParams
    {
      MyParams( ArgsT... args ) : rvalRefs { std::forward_as_tuple( args... ) } {} // The resulting forward_as_tuple tuple has rvalue reference data members 
      std::tuple< ArgsT... > rvalRefs;
    };
    
    
    void LegacySignature( long* legSigParam )
    {
      auto userArgsTuple( reinterpret_cast< MyParams< ARGSET >* >( legSigParam ) );
    
      // do something with the params like change num to 44 and tf to true;
      std::get< 0 >( userArgsTuple->rvalRefs ) = 44; // index types can probably be worked out using enums
      std::get< 1 >( userArgsTuple->rvalRefs ) = true;
    }
    
    int main()
    {
      int num { 33 };
      bool tf { false };
      MyParams< ARGSET > myParams( num, tf );
    
      std::unique_ptr< MyParams< ARGSET > > legSigParamPtr = std::make_unique< MyParams< ARGSET > >( myParams );
      LegacySignature( ( long* )legSigParamPtr.get() );
      assert( std::get< 0 >( legSigParamPtr->rvalRefs ) == 44 && std::get< 1 >( legSigParamPtr->rvalRefs ) == true );
    
      return 0;
    }