将函子对象传递给模板化类的构造函数

时间:2019-01-23 11:08:34

标签: c++ templates lambda stl functor

想象一下,我们有一个模板类。像这样

template<typename T>
class MyTemplateClass {
private: 
    T _v1, _v2;
public: 
    MyTemplateClass(T v1, T v2)
    {
        _v1 = v1;
        _v2 = v2;
    }
    bool Act()
    {
        return _v1 > _v2;
    }
}; 

//usage
MyTemplateClass<int> test(1, 2);
std::cout << test.Act() << std::endl;

现在我们想将函子对象/函数指针/ lambda传递给他的构造函数,以便我们可以使用它。

我已经尝试过类似的操作,但是遇到运行时错误

template<typename T, typename F>
class MyTemplateClass {
private: 
    T _v1, _v2;
    const F& _func;
public: 
    MyTemplateClass(T v1, T v2, F functor)
        :_func(functor)
    {
        _v1 = v1;
        _v2 = v2;
    }
    bool Act()
    {
        return _func(_v1, _v2);
    }
}; 

bool isGreater(int a, int b)
{
    return a > b;
} 


//later
    MyTemplateClass<int, std::function<bool(int, int)>> test(1, 2, isGreater);
    std::cout << test.Act() << std::endl; 

那么我如何实现此功能?有什么方法可以在不使用std :: function且不为functor对象传递typename的情况下使其工作? 我想用这种方式

MyTemplateClass<int> test(1, 2, isGreater);

2 个答案:

答案 0 :(得分:2)

不,由于引用了临时对象(functor),因此无法正常工作

const F& _func;
public: 
    MyTemplateClass(T v1, T v2, F functor)
    :_func(functor)

存储对象:

F _func;
public: 
    MyTemplateClass(T v1, T v2, F functor)
    :_func(std::move(functor))

或者在某些情况下,您知道对象的生存期,请将其作为const&:

传递
MyTemplateClass(T v1, T v2, const F& functor)

答案 1 :(得分:2)

  

我已经尝试过类似的操作,但是遇到运行时错误

正如Matthieu Brucher指出的their answer一样,您不能将_func存储为引用,因为将引用绑定到的对象会在构造函数调用结束时死亡。更改为按值存储_func将解决此问题。

  

有什么方法可以在不使用std :: function且不为functor对象传递typename的情况下使其工作?我想用这种方式

MyTemplateClass<int> test(1, 2, isGreater);

这实际上很容易做到。您仍然必须使用std::function作为存储类型和构造函数参数类型,但不必指定它。利用type alias,我们可以根据类成员的类型指定谓词类型。这给了我们

using predicate = std::function<bool(T, T)>;

,将其添加到类中后,我们可以将其修改为

template<typename T>
class MyTemplateClass {
public:
    using predicate = std::function<bool(T, T)>;
    MyTemplateClass(T v1, T v2, predicate functor)
        :_func(std::move(functor))
    {
        _v1 = v1;
        _v2 = v2;
    }
    bool Act()
    {
        return _func(_v1, _v2);
    }
private: 
    T _v1, _v2;
    predicate _func;
}; 

现在可以像这样使用

int main()
{
    MyTemplateClass<int> test(1, 2, isGreater);
    std::cout << test.Act() << std::endl; 
}