Passing a parameter package over an obsolete function signature using forward_as_tuple

In my application, I would like to pass a package of parameters over an obsolete function signature and change the values. Here is the 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 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 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 package a declarative value of l

0
source share
2 answers

The code below contains sample code to answer the question of how to pass a parameter package on top of an obsolete function 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; } 
0
source

I guess what you want is a pointer to your deprecated signature.

Here is the C ++ 11 approach.

 template<class Sig, class F> struct magic_callback_t; template<class R, class...Args, class F> struct magic_callback_t<R(Args...), F> { F f; void* pvoid() const { return this; } using result_sig = R(*)(void*, Args...); result_sig pfunc() const { return [](void* pvoid, Args...args)->R{ auto* self = static_cast<magic_callback_t*>(pvoid); return (self->f)(std::forward<Args>(args)...); }; } }; template<class Sig, class F> magic_callback_t<Sig, F> magic_callback( F&& f ) { return {std::forward<F>(f)}; } 

Now we just do this:

 auto callback = magic_callback( [&](){ // use whatever as if we where in the enclosing scope }); void(*)(void*) legacy_ptr = callback.pfunc(); legacy_ptr( callback.pvoid() ); 

will call the lambda you passed in to magic_callback .

If you want to store material as a tuple, you can. Just take a tuple in lambda, then use std::get to access it in the body of the lambda. Use mutable if you want it to change.

0
source

Source: https://habr.com/ru/post/1201829/


All Articles