C ++模板:作为模板类参数的功能

时间:2014-01-15 10:21:49

标签: c++ function templates parameters metaprogramming

所以在C ++中我们可以将函数作为模板参数传递,如下所示:

template <typename func>
int tester(func f)
{
    return f(10);
}

所以我有一个使用函数的模板类,我一直在使用它,每次我都会将函数和变量传递给它。

template <typename type_t>
class TCl
{
    ...
    template <typename func>
    int Test(func f, type_t Var>
    {
         // Blah blah blah
    }
};

但我想将该函数作为类模板参数之一,以使其更易于使用。 所以我首先尝试了这个:

template <typename func>
template <typename type_t, func f>
class TCl
{
    ...
};

但是当我编译它时,我得到:

编译器错误C3857:不允许使用多个类型参数列表

因为上帝禁止我的代码应该在我第一次尝试时编译。

现在我的问题是虽然我知道函数的参数类型(在这种情况下是size_t,size_t),但返回类型可以是任何东西,只要有适当的type_t比较运算符。

经过几个小时的在线阅读后,我找到了一个有效的解决方案。

template <typename type_t, typename ret_t, ret_t f(size_t, size_t)>
class TCl
{
    ...
};

虽然它有效但它破坏了代码的审美。我更喜欢在原始示例中指定func类型的东西,并且不必担心指定返回类型。

那么有人有任何建议吗?

此外,没有提升。

编辑: 解决!

谢谢你们。我使用了Jarod42的解决方案。

@Drax&amp;轨道中的轻盈竞赛:

我曾考虑过将这个类型放在手边,但它会给程序员带来负担来定义函数指针以便使用它,这似乎不必要地残忍:)

然而,Jarod42解决了使用宏和decltype运算符,我已经完全忘记了。

您的示例Jarod42存在轻微问题。

#define TCl_T(type_t, function) Tcl<type_t, decltype(function), function>

生成错误: 错误C1001:编译器中发生内部错误。

这解决了它。

#define TCl_T(type_t, function) Tcl<type_t, decltype(&function), function>

显然我们必须指明它是一个指针。

再次感谢帮助人员!

3 个答案:

答案 0 :(得分:2)

使用:

template <typename type_t, typename ret_t, ret_t f(size_t, size_t)>
class TCl;

您可以使用宏:

#define TCl_T(type_t, function) Tcl<type_t, decltype(function(0, 0)), function>

然后使用它:

// bool my_func(size_t, size_t);
TCl_T(int, my_func) tcl; // tcl is a Tcl<int, bool, my_func>

如果您将TCl更改为:

template <typename type_t, typename prototype_t, prototype_t f>
class TCl;

您可以使用宏:

#define TCl_T(type_t, function) Tcl<type_t, decltype(function), function>

答案 1 :(得分:1)

只需将模板参数放在同一行:

template <typename type_t, typename func, func f>
class TCl
{
    ...
};

答案 2 :(得分:1)

  

我非常喜欢在原始示例中指定func类型的内容,而不必担心指定返回类型。

好的,那就这么简单! :-)我不明白你为什么从传递整个函数类型作为模板参数,将其拆分为返回类型和参数类型。并且,在这样做时,您介绍了您所陈述的问题。但是你没有解释为什么你做了这个改变。

为什么不简单:

template <typename type_t, typename func_t, func_t f>
class TCl
{
    // ...
};

这是你自己的方法的逻辑演变,不是吗?

这是一个有效的例子:

#include <iostream>

template <typename type_t, typename func_t, func_t f>
struct T
{
    T() { f(); }

    type_t a;   /**< Irrelevant here, but gives your `type_t` something to do */
};

void foo() { std::cout << "A\n"; }
int  bar() { std::cout << "B\n"; return 0; }

int main()
{
    T<int, void(*)(), &foo> t1;
    T<int, int (*)(), &bar> t2;
}

// Output:
//  A
//  B

Live demo

遗憾的是,你无法在 template-argument-list 中使用更多的演绎。为了缩短调用次数,Jarod42对宏有一个有趣的想法,尽管我不确定它是否会改善美感。

我想知道这是否意味着你的断言:

  

使该函数成为类模板参数之一,以便于使用

是假的。