使用 forward_as_tuple 通过遗留函数签名传递参数包
passing a parameter pack over a legacy function signature using forward_as_tuple
在我的应用程序中,我想通过遗留函数签名传递参数包,并更改值。这是用我的评论尝试说明我的问题的代码:
#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;
}
有没有办法让参数包成为可声明的左值?
我假设您想要的是一个指向旧签名的函数指针。
这是一个 C++11 方法。
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)};
}
现在我们这样做:
auto callback = magic_callback( [&](){
// use whatever as if we where in the enclosing scope
});
void(*)(void*) legacy_ptr = callback.pfunc();
legacy_ptr( callback.pvoid() );
将调用您传递给 magic_callback
的 lambda。
如果您想将内容存储为元组,可以。只需捕获 lambda 中的元组,然后使用 std::get
在 lambda 主体中访问它。如果您希望它可变,请使用 mutable
。
下面的代码修复了示例代码,以便它回答有关如何使用 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;
}
在我的应用程序中,我想通过遗留函数签名传递参数包,并更改值。这是用我的评论尝试说明我的问题的代码:
#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;
}
有没有办法让参数包成为可声明的左值?
我假设您想要的是一个指向旧签名的函数指针。
这是一个 C++11 方法。
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)};
}
现在我们这样做:
auto callback = magic_callback( [&](){
// use whatever as if we where in the enclosing scope
});
void(*)(void*) legacy_ptr = callback.pfunc();
legacy_ptr( callback.pvoid() );
将调用您传递给 magic_callback
的 lambda。
如果您想将内容存储为元组,可以。只需捕获 lambda 中的元组,然后使用 std::get
在 lambda 主体中访问它。如果您希望它可变,请使用 mutable
。
下面的代码修复了示例代码,以便它回答有关如何使用 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;
}