非类型模板参数......这是一个模板!(C++)

dam*_*ape 6 c++ templates marshalling wrapper

我基本上希望为通用C函数生成包装器,而无需手动指定类型.所以我有一个带有固定原型的回调,但是我需要根据包装函数的类型在包装器中做一些特殊的代码......所以基本上我在考虑在类模板中使用静态方法将我的函数包装到一致的接口,例如:

// this is what we want the wrapped function to look like
typedef void (*callback)(int); 
void foobar( float x ); // wrappee

// doesn't compile
template< T (*f)(S) > // non-type template param, it's a function ptr
struct Wrapper
{
  static void wrapped(int x)
  {
     // do a bunch of other stuff here
     f(static_cast<S>(x)); // call wrapped function, ignore result

  }
}
Run Code Online (Sandbox Code Playgroud)

然后我想做一些像:

AddCallback( Wrapper<foobar>::wrapped );
Run Code Online (Sandbox Code Playgroud)

但是,问题是我不能继续在Wrapper模板中的函数参数中使用"S",我必须先将其列为参数:

template< class T, class S, T (*f)(S) >
struct Wrapper
// ...
Run Code Online (Sandbox Code Playgroud)

但这意味着使用(Wrapper<void,float,foobar>::wrapped)会更加痛苦,理想情况下我只想传递函数指针并让它自动计算出参数类型(和返回类型).要清楚,在包装函数内部我需要引用函数指针的类型(所以我需要一些等价的S或T).

有办法做到这一点吗?

bdo*_*lan 5

您可能希望考虑的一件事是使用LLVM或类似的方法在运行时生成适当的trampoline函数.或者这是一个静态解决方案:

#include <iostream>

void f(float f) { std::cout << f << std::endl; }

template<typename T, typename S> struct static_function_adapter {
        template<T(*f)(S)> struct adapt_container {
                static void callback(int v) {
                        f(static_cast<S>(v));
                }
        };

        template<T(*f)(S)> adapt_container<f> adapt() const {
                return adapt_container<f>();
        }
};

template<typename T, typename S> struct static_function_adapter<T, S> get_adapter(T (*)(S)) {
        return static_function_adapter<T, S>();
}

#define ADAPTED_FUNCTION(f) (&get_adapter(f).adapt<f>().callback)

int main() {
        void (*adapted)(int) = ADAPTED_FUNCTION(f);
        adapted(42);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

get_adapter函数允许我们推断参数和返回类型; adapt()然后将其转换为在实际函数上参数化的类型,最后我们在回调中获得静态函数.


Tim*_*ter 0

如果您使用返回“包装”的函数而不是直接引用它,则编译器将尝试自动匹配函数调用的模板参数。

编辑:那这个呢?

int foobar( float x ); // wrappee

template <typename T, typename S>
struct Wrapper {
    typedef T (*F)(S);
    F f;

    Wrapper(F f) : f(f) { }

    void wrapped(S x) {
        // do a bunch of other stuff here
        f(x); // call wrapped function, ignore result
    }
};

template <typename T, typename S>
Wrapper<T,S> getWrapper(T (*f)(S)) {
    return Wrapper<T,S>(f);
}

...
getWrapper(foobar).wrapped(7);
Run Code Online (Sandbox Code Playgroud)