将函数指针作为非类型模板参数传递
Passing a function pointer as non-type template parameter
我有这个模板功能,效果很好:
template<typename RES, typename... PARMS> SQInteger GlobalBind(RES(*fn)(PARMS... parms), const char *sqName, HSQUIRRELVM v)
这样称呼:
GlobalBind(aFunction, "aName", vm);
它的范围是将函数 fn
绑定到脚本引擎。
以这种方式使用它,我必须在脚本引擎中保留 fn
指针和代理模板指针;使用 fn
作为参数调用代理模板(此处未显示),执行一些操作,然后调用 fn
.
我想要实现的是从函数调用中删除 fn
指针,并将其作为参数放入模板中,如下所示:
template<typename RES, typename... PARMS, RES(*fn)(PARMS...)> SQInteger GlobalBind(const char *sqName, HSQUIRRELVM v)
因此,为每个不同的fn
实例化一个特定的模板,这意味着我可以避免脚本语言中的fn
指针;电话应该是:
GlobalBind<aFunction>("aName", vm);
模板声明被编译器接受,但是调用带来错误,甚至在aFunction
之前添加参数类型,像这样(假设aFunction
returns和int
并且有 const char *
作为参数):
GlobalBind<int, const char *, aFunction>("aName", vm);
有没有办法实现这个结果(前者,没有参数列表)?
编辑:
为了简化问题,是模板
template<typename RES, typename... PARMS, RES(*fn)(PARMS...)> RES TEST(PARMS... parms) {
return fn(parms...);
}
一个有效的?如果是的话……应该怎么称呼它?
我试过了:
int testfn(const char *s) { return strlen(s); }
TEST<testfn>("aString"); << ERROR
TEST<int, const char *, testfn>("aString"); << ERROR
编辑2:
这个:
template<int (*fn)(const char *)> int TEST2(const char *s) {
return fn(s);
}
TEST2<testfn>("aString");
有效,但对我的目的没有用
template<class T, T t>
struct constant_t:std::integral_constant<T,t>{
constexpr operator T()const { return t; }
constexpr constant_t(){}
};
#define TYPEDARG(...) \
typename std::decay<decltype(__VA_ARGS__)>::type, \
__VA_ARGS__
现在 constant_t<TYPEDARG(foo)>
是一个类型,如果 foo
是一个非重载函数并且它们调用 foo
.
则可以调用其实例
在 c++17 中变为:
template<auto x>
using constant_t=std::integral_constant<std::decay_t<decltype(x)>,x>;
并且使用起来很简单 constant_t<foo>
,没有所有额外的噪音。
template<class Fn, class R, class... Args>
R test(Args&&... args) {
return Fn{}(std::forward<Args>(args)...);
}
int foo( int a, int b ) { return a+b; }
int r = test< constant_t<TYPEDARG(foo)>, int, int, int >( 3, 4 );
找到了一个(丑陋的)解决方案,但它也适用于重载函数:
int myFunc(const char *s) {
return strlen(s);
}
const char *myFunc(int i) {
return "it's me";
}
template<typename FN, FN fn, typename RES, typename... PARMS> RES _DISPATCH(PARMS... parms) {
return fn(parms...);
}
#define DISPATCH(RES, FN, ...) _DISPATCH<RES(*)(__VA_ARGS__), FN, RES, __VA_ARGS__>
Cout() << (void *)DISPATCH(int, myFunc, const char *) << "\n";
Cout() << (void *)DISPATCH(const char *, myFunc, int) << "\n";
DISPATCH() 宏构建了一个调度程序,我可以获得它的 C 地址并传递给我的脚本引擎。
确实,我宁愿有一个没有宏的解决方案。仍然对更好的解决方案持开放态度!
我有这个模板功能,效果很好:
template<typename RES, typename... PARMS> SQInteger GlobalBind(RES(*fn)(PARMS... parms), const char *sqName, HSQUIRRELVM v)
这样称呼:
GlobalBind(aFunction, "aName", vm);
它的范围是将函数 fn
绑定到脚本引擎。
以这种方式使用它,我必须在脚本引擎中保留 fn
指针和代理模板指针;使用 fn
作为参数调用代理模板(此处未显示),执行一些操作,然后调用 fn
.
我想要实现的是从函数调用中删除 fn
指针,并将其作为参数放入模板中,如下所示:
template<typename RES, typename... PARMS, RES(*fn)(PARMS...)> SQInteger GlobalBind(const char *sqName, HSQUIRRELVM v)
因此,为每个不同的fn
实例化一个特定的模板,这意味着我可以避免脚本语言中的fn
指针;电话应该是:
GlobalBind<aFunction>("aName", vm);
模板声明被编译器接受,但是调用带来错误,甚至在aFunction
之前添加参数类型,像这样(假设aFunction
returns和int
并且有 const char *
作为参数):
GlobalBind<int, const char *, aFunction>("aName", vm);
有没有办法实现这个结果(前者,没有参数列表)?
编辑: 为了简化问题,是模板
template<typename RES, typename... PARMS, RES(*fn)(PARMS...)> RES TEST(PARMS... parms) {
return fn(parms...);
}
一个有效的?如果是的话……应该怎么称呼它? 我试过了:
int testfn(const char *s) { return strlen(s); }
TEST<testfn>("aString"); << ERROR
TEST<int, const char *, testfn>("aString"); << ERROR
编辑2: 这个:
template<int (*fn)(const char *)> int TEST2(const char *s) {
return fn(s);
}
TEST2<testfn>("aString");
有效,但对我的目的没有用
template<class T, T t>
struct constant_t:std::integral_constant<T,t>{
constexpr operator T()const { return t; }
constexpr constant_t(){}
};
#define TYPEDARG(...) \
typename std::decay<decltype(__VA_ARGS__)>::type, \
__VA_ARGS__
现在 constant_t<TYPEDARG(foo)>
是一个类型,如果 foo
是一个非重载函数并且它们调用 foo
.
在 c++17 中变为:
template<auto x>
using constant_t=std::integral_constant<std::decay_t<decltype(x)>,x>;
并且使用起来很简单 constant_t<foo>
,没有所有额外的噪音。
template<class Fn, class R, class... Args>
R test(Args&&... args) {
return Fn{}(std::forward<Args>(args)...);
}
int foo( int a, int b ) { return a+b; }
int r = test< constant_t<TYPEDARG(foo)>, int, int, int >( 3, 4 );
找到了一个(丑陋的)解决方案,但它也适用于重载函数:
int myFunc(const char *s) {
return strlen(s);
}
const char *myFunc(int i) {
return "it's me";
}
template<typename FN, FN fn, typename RES, typename... PARMS> RES _DISPATCH(PARMS... parms) {
return fn(parms...);
}
#define DISPATCH(RES, FN, ...) _DISPATCH<RES(*)(__VA_ARGS__), FN, RES, __VA_ARGS__>
Cout() << (void *)DISPATCH(int, myFunc, const char *) << "\n";
Cout() << (void *)DISPATCH(const char *, myFunc, int) << "\n";
DISPATCH() 宏构建了一个调度程序,我可以获得它的 C 地址并传递给我的脚本引擎。 确实,我宁愿有一个没有宏的解决方案。仍然对更好的解决方案持开放态度!