【问题标题】:Having class or function as template parameter将类或函数作为模板参数
【发布时间】:2011-05-27 16:53:18
【问题描述】:

我不确定要搜索什么,所以我会尽量解释清楚。在 STL 中,std::set 定义为

template <class Key, class Compare, class Allocator> class set;

来自http://cplusplus.com

Compare:比较类:接受两个与容器元素相同类型的参数并返回一个布尔值的类。表达式 comp(a,b),其中 comp 是此比较类的对象,a 和 b 是容器 [...] 的元素。这可以是实现函数调用运算符的类,也可以是指向函数[...]的指针。

我说的是Compare模板参数。

所以如果我要编写一个模板类,它有一个模板参数,它是一个实现函数调用运算符的类,我会写

template <class T, class Combine>
class MyClass
{
public:
    Combine func;
    MyClass()
    {
        func = Combine();
    }
    T do_it(T a, T b)
    {
        return func(a, b);
    }
};

class IntCombine
{
public:
    int operator () (int a, int b)
    {
        return a + b;
    }
};

//...
MyClass<int, IntCombine> ob;
ob.do_it(4, 5);

或者,如果我要这样写第二个模板参数是一个函数:

template <class T, T Combine(T, T)>
class MyClass
{
public:
    Combine func;
    MyClass()
    {
        func = Combine;
    }
    T do_it(T a, T b)
    {
        return func(a, b);
    }
};

int IntCombine(int a, int b)
{
    return a + b;
}

//...
MyClass<int, IntCombine> ob;
ob.do_it(4, 5);

但是,在 STL 中,您可以使用任何一种方式使用 set 类。这是如何实现的?上面的代码只有在我的ob 定义中的第二个模板参数分别是实现operator () 的类或函数时才有效,但我不能编写MyClass 以便两者都可以工作。

我的示例可能看起来毫无用处。基本上我想写一个可以组合元素的容器,它和 STL 容器一样通用。

【问题讨论】:

    标签: c++ templates operator-overloading function-pointers


    【解决方案1】:

    仅当我定义的 ob 中的第二个模板参数分别是实现运算符 () 的类或函数时,上面的代码才有效,但我不能编写 MyClass 以便两者都能工作。

    是的,你可以:

    template <typename F>
    struct foo {
        F f;
        void call() {
            f();
        }
    };
    
    void function() {
        std::cout << "function called" << std::endl;
    }
    
    int main() {
        foo<void(*)()> a = { function };
        a.call();
    }
    

    这完全遵循example of the std::set constructor。重要的一点是,如果您使用的是函数指针,则模板参数是 not 那个函数指针,它是函数指针的 type(此处为 void (*)()) .您需要单独存储实际的函数指针。

    【讨论】:

    • 这里还值得注意的是,实际上可以通过模板传递函数指针。
    • @DeadMG:正确,但就像将函数(不是 pointer)传递给模板参数的情况一样,这不再适用于上述签名,即typename 我们必须在模板参数列表中包含函数指针的类型。
    • template&lt;typename T, T t&gt; 是完全合法的。
    • @DeadMG:是的,我知道?我的观点是你不能有一个模板声明&lt;typename T&gt;(在签名上方)并用函数指针实例化它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多