C++ C++;11可变模板函数呼叫转移
我试图弄清楚如何创建一个C++11模板函数,它将在两个约定之间转换函数调用:第一个是使用Variant(注意:Variant是一种多态类型,它是子类IntVariable、DoubleVariant等的基础),第二个是C函数调用 我们知道编译时的每一条信息:参数计数是参数的数量,参数/返回类型取决于'cfunc'变量类型C++ C++;11可变模板函数呼叫转移,c++,templates,c++11,variadic-templates,C++,Templates,C++11,Variadic Templates,我试图弄清楚如何创建一个C++11模板函数,它将在两个约定之间转换函数调用:第一个是使用Variant(注意:Variant是一种多态类型,它是子类IntVariable、DoubleVariant等的基础),第二个是C函数调用 我们知道编译时的每一条信息:参数计数是参数的数量,参数/返回类型取决于'cfunc'变量类型 // We will assume that the two following functions are defined with their correct // spe
// We will assume that the two following functions are defined with their correct
// specializations.
template < typename T >
Variant * convertToVariant( T t );
template < typename T >
T convertFromVariant( Variant * variant );
// The following function is incomplete, the question is how to convert the
// variant parameters into a C function call ?
template < typename Return, typename... Arguments >
Variant * wrapCFunction< Return cfunc( Args... ) >(int argc, Variant ** argv) {
// Here comes the magic call of cfunc, something like :
if ( argc != mpl::count< Args... >::value )
throw std::runtime_error( "bad argument count" );
return cfunc( convertFromVariant< Args... >( argv[ X ] )... );
}
// Example use case :
int foo( int a, int b );
int main(void) {
int argc = 2;
Variant * argv[2] = { new IntVariant( 5 ), new IntVariant( 6 ) };
Variant * res = wrapCFunction< foo >( argc, argv );
IntVariant * intRes = dynamic_cast< IntVariant >( res );
return intRes ? intRes->value : -1;
}
//我们假设以下两个函数都是用正确的
//专业化。
模板
变量*convertToVariant(T);
模板
T转换变量(变量*变量);
//下面的函数不完整,问题是如何转换
//将变量参数转换为C函数调用?
模板
Variant*wrapc函数(int argc,Variant**argv){
//下面是cfunc的神奇召唤,比如:
如果(argc!=mpl::count::值)
抛出std::runtime_错误(“错误参数计数”);
返回cfunc(convertFromVariant(argv[X]));
}
//示例用例:
int foo(int a、int b);
内部主(空){
int argc=2;
Variant*argv[2]={new IntVariant(5),new IntVariant(6)};
变量*res=wrapc函数(argc,argv);
IntVariant*intRes=dynamic_cast(res);
返回intRes?intRes->值:-1;
}
类变量;
模板Variant*convertToVariant(T);
模板T convertFromVariant(Variant*Variant);
模板
结构WrapCFunctionImpl{
模板
结构Impl{
typedef typename Impl::Type Type;
};
};
模板
模板
结构wrapcfonfictionimpl::Impl{
typedef Impl类型;
静态变量*运行(返回cfunc(参数…,变量**argv){
返回convertToVariant(cfunc(convertFromVariant(argv[argIndexes])…);
}
};
模板
Variant*wrapc函数(返回cfunc(参数…),Variant**argv){
返回wrapcfonfictionimpl::template Impl::Type::run(cfunc,argv);
}
int foo(int,int);
变型*f(变型**x){
返回wrapc函数(foo,x);
}
这里最大的困难是递归生成数组中的索引。可能有更简单的方法,但这是可行的。classvariant;
模板Variant*convertToVariant(T);
模板T convertFromVariant(Variant*Variant);
模板
结构WrapCFunctionImpl{
模板
结构Impl{
typedef typename Impl::Type Type;
};
};
模板
模板
结构wrapcfonfictionimpl::Impl{
typedef Impl类型;
静态变量*运行(返回cfunc(参数…,变量**argv){
返回convertToVariant(cfunc(convertFromVariant(argv[argIndexes])…);
}
};
模板
Variant*wrapc函数(返回cfunc(参数…),Variant**argv){
返回wrapcfonfictionimpl::template Impl::Type::run(cfunc,argv);
}
int foo(int,int);
变型*f(变型**x){
返回wrapc函数(foo,x);
}
这里最大的困难是递归生成数组中的索引。可能有更简单的方法,但这是可行的。使用,这相当简单:
template<unsigned...> struct indices{};
template<unsigned N, unsigned... Is>
struct indices_gen : indices_gen<N-1, N-1, Is...>{};
template<unsigned... Is>
struct indices_gen<0, Is...> : indices<Is...>{};
// assuming the parameters were actually like this
template<typename Return, typename... Args, unsigned... Is>
Variant* wrapCFunction(Return (*cfunc)(Args...), int argc, Variant** argv, indices<Is...>) {
return cfunc(convertFromVariant<Args>(argv[Is])...);
}
template<typename Return, typename... Args>
Variant* wrapCFunction(Return (*cfunc)(Args...), int argc, Variant** argv) {
if (argc != sizeof...(Args))
throw std::runtime_error("bad argument count");
return wrapCFunction(cfunc, argc, argv, indices_gen<sizeof...(Args)>());
}
模板结构索引{};
模板
结构索引:索引{};
模板
结构索引:索引{};
//假设参数实际上是这样的
模板
Variant*wrapc函数(返回(*cfunc)(Args…),int argc,Variant**argv,index){
返回cfunc(convertFromVariant(argv[Is])…);
}
模板
Variant*wrapc函数(返回(*cfunc)(Args…),int argc,Variant**argv){
如果(argc!=sizeof…(Args))
抛出std::runtime_错误(“错误参数计数”);
返回wrapc函数(cfunc、argc、argv、index_gen());
}
请注意代码中的一些更改。首先,sizeof…(Args)
生成包中的参数数。其次,我修复了函数的签名,将其作为实际参数传递给cfunc
。使用,这相当简单:
template<unsigned...> struct indices{};
template<unsigned N, unsigned... Is>
struct indices_gen : indices_gen<N-1, N-1, Is...>{};
template<unsigned... Is>
struct indices_gen<0, Is...> : indices<Is...>{};
// assuming the parameters were actually like this
template<typename Return, typename... Args, unsigned... Is>
Variant* wrapCFunction(Return (*cfunc)(Args...), int argc, Variant** argv, indices<Is...>) {
return cfunc(convertFromVariant<Args>(argv[Is])...);
}
template<typename Return, typename... Args>
Variant* wrapCFunction(Return (*cfunc)(Args...), int argc, Variant** argv) {
if (argc != sizeof...(Args))
throw std::runtime_error("bad argument count");
return wrapCFunction(cfunc, argc, argv, indices_gen<sizeof...(Args)>());
}
模板结构索引{};
模板
结构索引:索引{};
模板
结构索引:索引{};
//假设参数实际上是这样的
模板
Variant*wrapc函数(返回(*cfunc)(Args…),int argc,Variant**argv,index){
返回cfunc(convertFromVariant(argv[Is])…);
}
模板
Variant*wrapc函数(返回(*cfunc)(Args…),int argc,Variant**argv){
如果(argc!=sizeof…(Args))
抛出std::runtime_错误(“错误参数计数”);
返回wrapc函数(cfunc、argc、argv、index_gen());
}
请注意代码中的一些更改。首先,
sizeof…(Args)
生成包中的参数数。其次,我修正了函数的签名,将cfunc
作为实际参数传递。出于好奇,你到底为什么想要运行时变量而不是编译时变量,例如?@ildjarn我使用运行时变量在动态语言的运行时库中保存值(如Zend引擎中的zValue).我能想到的最好的答案,我只是想问一下。:-]出于好奇,你到底为什么想要运行时变量而不是编译时变量,例如?@ildjarn我正在使用运行时变量在动态语言的运行时库中保存值(如Zend引擎中的zValue)。我能想到的最好答案是,我想我会问::-]哇,谢谢,我不知道这个把戏。我真的很喜欢C++11。。。然而,有趣的是,C++元编程仍然需要这么多的黑魔法:“@尼森:我不会真正称之为“黑魔术师”,因为这个技巧本身是相当容易理解的。您基本上生成了一组可变参数索引。此生成是通过p的递归完成的