将函数指针作为非类型模板参数传递

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之前添加参数类型,像这样(假设aFunctionreturns和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.

则可以调用其实例

中变为:

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 地址并传递给我的脚本引擎。 确实,我宁愿有一个没有宏的解决方案。仍然对更好的解决方案持开放态度!