将仿函数对象传递给模板化 class 的构造函数
Pass an functor object to constructor of templated class
假设我们有一个模板 class。像这样
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 并且不为我的仿函数对象传递类型名的情况下使它工作吗?
我想这样用
MyTemplateClass<int> test(1, 2, isGreater);
不,由于对临时对象 (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)
I've tried something like this, but got runtime-error
As Matthieu Brucher pointed out 您不能将 _func
存储为引用,因为您将引用绑定到的对象在构造函数调用结束时死亡。更改为按值存储 _func
将解决此问题。
Is there any way to make this working without using std::function and without passing typename for my functor object? I would like to use it this way
MyTemplateClass<int> test(1, 2, isGreater);
这其实很容易做到。您仍然必须使用 std::function
作为存储类型和构造函数参数类型,但不必指定它。利用 type alias 我们可以根据 class 成员的类型指定谓词类型。这给了我们
using predicate = std::function<bool(T, T)>;
将其添加到 class 后,我们可以将其修改为
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;
}
假设我们有一个模板 class。像这样
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 并且不为我的仿函数对象传递类型名的情况下使它工作吗? 我想这样用
MyTemplateClass<int> test(1, 2, isGreater);
不,由于对临时对象 (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)
I've tried something like this, but got runtime-error
As Matthieu Brucher pointed out _func
存储为引用,因为您将引用绑定到的对象在构造函数调用结束时死亡。更改为按值存储 _func
将解决此问题。
Is there any way to make this working without using std::function and without passing typename for my functor object? I would like to use it this way
MyTemplateClass<int> test(1, 2, isGreater);
这其实很容易做到。您仍然必须使用 std::function
作为存储类型和构造函数参数类型,但不必指定它。利用 type alias 我们可以根据 class 成员的类型指定谓词类型。这给了我们
using predicate = std::function<bool(T, T)>;
将其添加到 class 后,我们可以将其修改为
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;
}