C++ 中的通用 Functor 类
我试图在此处的线程之上构建: 可变长度模板参数列表? 有一个默认的 Functor 类,这只是出于学术兴趣。我的目标是构建一个通用的 Fucntor 类:给定类名、方法名和参数类型(可变长度),它构建一个具有 operator() 方法的类,该方法采用模板 args 中指定的可变数量的参数类型和接受一个指针并应用给定的方法。想象一个类:
class MyClass
{
public:
float Fraction( float n, int m)
{
return n/m;
}
int Increment(int n)
{
return n+1;
}
} ;
以及一个可以在任何函数中使用的模板化函子类:
int k = FunctorClass<MyClass, Increment, int, int /*return type*/> (3);
assert(k == 4);
float l = FunctorClass<MyClass, Fraction, float, int, float, /*return type*/> (4,3);
assert(l == (4/3));
可以构造这样的函子类吗? 旁注:不能使用 Variadic 模板,(在 VS2010 中构建,没有...模板参数) 感谢您的帮助
I was trying to built atop the thread here: Variable length template arguments list?
to have a default Functor class, this is only of academic interest. My goal is to build a generic Fucntor class: given a class name, method name and argument types(of variable length), it builds a class that has an operator() method which takes variable number of arguments of type specified in template args and takes a pointer and applies the given method. Imagine a class thus:
class MyClass
{
public:
float Fraction( float n, int m)
{
return n/m;
}
int Increment(int n)
{
return n+1;
}
} ;
And a templatized functor class that can be used in any function thus:
int k = FunctorClass<MyClass, Increment, int, int /*return type*/> (3);
assert(k == 4);
float l = FunctorClass<MyClass, Fraction, float, int, float, /*return type*/> (4,3);
assert(l == (4/3));
Can such a functor class be constructed?
Sidenote: Cant use Variadic templates, (building in VS2010, no ... template arguments)
Thanks for the help
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这当然是可行的,例如 Boost bind() 使用这种方法在幕后。但是,如果没有变量,您将无法获得完全的通用性,因为您将被限制为固定数量的模板参数,并且您需要为您想要支持的每个不同数量的参数键入实现。另外,如果没有右值引用,您将无法获得完美的转发。
也就是说,您尝试使用它的方式是行不通的:在声明成员函数时,您不能只命名它们。您需要使用例如
&MyClass::Increment
和&MyClass::Fraction
来获取正确的成员函数点。如果成员函数重载,则需要消除它的歧义。由于您显然希望启用此函数对象用于非静态成员函数,因此您还需要提供一个要调用该成员函数的对象。最合理的方法是将对象的引用作为函数对象类的构造函数参数传递,并存储它以便在调用函数时使用。也就是说,使用看起来有些不同,但可以通过某种工厂函数来简化。这是一个调整各种内容并实现相应功能对象模板的版本:
This is certainly doable, e.g. Boost bind() uses this approach under the hood. Without variadics you won't get full generality, however, because you will be limited to a fixed number of template arguments and you need to type the implementation for each different number of arguments you want to support. Also, without rvalue references you won't get perfect forwarding.
That said, the way you are trying to use it won't work: when stating the member functions, you can't just name them. You need to obtain the correct member function point using e.g.
&MyClass::Increment
and&MyClass::Fraction
. If the member function is overloaded, you need to disambiguate it.Since you apparently want to enable the use of this function object for non-static member functions, you also need to provide an object on which the member function is to be called. The most reasonable approach for this is to pass a reference to the object as a constructor argument of the function object class and to store it to be used whenever the function is being called. That is, the use looks somewhat different but it can be simplified with some sort of factory function. Here is a version which adjusts the various things and implements a corresponding function object template:
我不确定你是否需要变量来完成这个任务。考虑以下接口...
抽象接口不是成熟的类,它们可以包含部分实现,例如函数签名和一些数据成员。使用模板,您可以概括返回类型。但是你说的参数列表呢?
请注意接口中没有构造函数。在具体类(或派生类)中,您可以将变量参数列表的负担传递给构造函数,就像这样......
您可以通过构造函数根据具体情况处理参数列表。
显式构造函数在声明时需要参数列表,因此您将在此处获取变量列表。所以在实践中......
你会很酷。
I'm not sure you would need variadics to pull this off. Consider the following interface...
Abstract interfaces are not full-blown classes, they can contain a partial implementation such as function signatures and some data members. With the template, you can generalized a return type. But what about the argument list you say?
Note how there is no constructor in the interface. In your concrete class (or derived classes) you can pass the burden of variable argument lists to the constructor, like so...
You deal with the argument list on a case by case basis through the constructor.
The explicit constructor requires an argument list upon declaration, so you'll get your variable list here. So in practice...
...and you'd be cool.