1

我似乎无法通过以下方式使用多层模板,

template <typename T>
template <T value>
void printValueAsInteger()
{
    printf("value as integer is %i\n", (int) value);
}

所以它可以被称为:

printValueAsInteger<123>();

它会导致以下错误消息:too many template-parameter-lists

如果我使用template <typename T, T value>with printValueAsInteger<int, 123>(),它可以工作,但这需要我明确指定类型。我怎样才能让它printValueAsInteger<123>()打印出来value as integer is 123

编辑:

我会更具体地说明我需要这个。我的目标是将成员函数作为函数指针传递,我想用模板包装它:

template <typename T>
template <T* instance, void (T::*method)()>
void wrappedMethod()
{
    (instance->*method)();
}
void callFunction(void (*function)())
{
    (*function)();
}

然后像这样传递它:

Base *instance = new Derived;
callFunction(&wrappedFunction<instance, Base::method>);

编辑:

呃,我刚刚意识到我可能不应该(也不能)使用运行时定义的变量作为模板参数。我现在正在尝试使用一个用其他模板参数实例化的类来解决它,并创建一个使用该类的模板函数。或类似的东西。不,不起作用。

请注意,我无法更改 callFunction 的签名,因为它是第三方 API 的一部分。

最后!

我将以下内容放在标题中,

class Callable
{
public:
    virtual ~Callable() { }
    virtual void call() { }
};

typedef void (*functionPtr)();
extern unsigned nextMethodId;
extern functionPtr wrappedMethods[];
extern Callable *boundMethods[];

template <unsigned I>
class MethodWrapper
{
public:
    static void function();
};

template <typename T>
class Method : public Callable
{
public:
    Method(T* instance, void (T::*method)());
    virtual void call();
private:
    T* instance;
    void (T::*method)();
};

template <typename T>
Method<T>::Method(T* instance, void (T::*method)())
    : instance(instance), method(method) {
}

template <typename T>
void Method<T>::call()
{
    if (instance && method)
        (instance->*method)();
}

template <typename T>
static functionPtr bindMethod(T* instance, void (T::*method)())
{
    boundMethods[nextMethodId] = new Method<T>(instance, method);
    return (void (*)()) wrappedMethods[nextMethodId++];
}

这在源文件中:

#include "<insert header name here>.h"

unsigned nextMethodId = 0;
functionPtr wrappedMethods[] = {
    &MethodWrapper<0>::function,
    &MethodWrapper<1>::function,
    &MethodWrapper<2>::function
};
Callable *boundMethods[sizeof(wrappedMethods) / sizeof(functionPtr)];

template <unsigned I>
void MethodWrapper<I>::function()
{
    boundMethods[I]->call();
}

我可以这样使用它:

Base *instance = new Derived;
void (*function)() = bindMethod(instance, &Base::method);
callFunction(function);

它成功调用了派生实例的方法版本。遗憾的是,允许绑定的方法数量是固定的(本例中为三个),但它很容易扩展。

4

2 回答 2

1

一个简单的转换是将运行时值作为一个函子的构造函数的参数,该函子包含实例指针和指向成员函数的指针。使用地点的语法将从:

Base *instance = new Derived;
callFunction(&wrappedFunction<instance, Base::method>);

至:

callFunction( WrappedFunction<Base,&Base::method>( instance ) );

类型的实现WrappedFunction其实很简单,所以我把它留作练习。请注意,这种方法的一个主要变化是参数callFunction变为仿函数,而不是函数指针。

在 C++11(或使用 boost)中,最简单的方法是不编写任何代码,只使用可用资源。将签名更改callFunction为:

void callFunction( function<void ()> f );

并用于bind拨打电话:

callFunction( bind( &Base::method, instance ) );
于 2012-07-22T21:44:45.980 回答
0

对于您的第一个示例,您可以指定int模板参数的类型:

template <int I>
void printValueAsInteger()
{
    printf("value as integer is %i\n", I);
}

对于您的编辑,您不能使用已经提到的运行时定义的变量,因为模板是在编译时使用的。使用std::bindandstd::function会使事情变得简单:

void callFunction(std::function<void()> f)
{
    f();
}

Base *instance = new Derived;
callFunction(std::bind(&Base::method, instance));

评论后

我能想到的唯一方法是让你的成员函数static

callFunction(&Base::method); // Okay if the method is declared static

或者使用带有全局实例的全局包装函数:

Base *instance = new Derived; // Global
void wrapperFunction()
{
    instance->method();
}

callFunction(wrapperFunction);
于 2012-07-22T20:52:16.977 回答