函子类在构造函数中工作
我使用 C++ 模板传入策略函子来更改函数的行为。 效果很好。 我传递的函子是一个无状态类,没有存储,它只是以经典函子方式重载 () 运算符。
template <typename Operation> int foo(int a)
{
int b=Operation()(a);
/* use b here, etc */
}
我经常这样做,而且效果很好,而且我经常使用传入的 6 或 7 个模板化函子来制作模板!
然而,我既担心代码的优雅性,又担心效率。 函子是无状态的,所以我假设 Operation() 构造函数是免费的,并且函子的求值与内联函数一样高效,但像所有 C++ 程序员一样,我总是有一些挥之不去的疑问。
我的第二个问题是我是否可以使用另一种函子方法。该方法不会覆盖 () 运算符,但会在构造函数中执行所有操作作为副作用! 比如:
struct Operation {
Operation(int a, int &b) { b=a*a; }
};
template <typename Operation> int foo(int a)
{
int b;
Operation(a,b);
/* use b here, etc */
}
我从未见过有人使用构造函数作为仿函数的“工作”,但看起来它应该可以工作。 有什么优势吗? 有什么缺点吗? 我确实喜欢删除奇怪的双括号 "Operator()(a)" ,但这可能只是为了美观。
I'm using C++ templates to pass in Strategy functors to change my function's behavior. It works fine. The functor I pass is a stateless class with no storage and it just overloads the () operator in the classic functor way.
template <typename Operation> int foo(int a)
{
int b=Operation()(a);
/* use b here, etc */
}
I do this often, and it works well, and often I'm making templates with 6 or 7 templated functors passed in!
However I worry both about code elegance and also efficiency. The functor is stateless so I assume the Operation() constructor is free and the evaluation of the functor is just as efficient as an inlined function, but like all C++ programmers I always have some nagging doubt.
My second question is whether I could use an alternate functor approach.. one that does not override the () operator, but does everything in the constructor as a side effect!
Something like:
struct Operation {
Operation(int a, int &b) { b=a*a; }
};
template <typename Operation> int foo(int a)
{
int b;
Operation(a,b);
/* use b here, etc */
}
I've never seen anyone use a constructor as the "work" of a functor, but it seems like it should work. Is there any advantage? Any disadvantage? I do like the removal of the strange doubled parenthesis "Operator()(a)" , but that's likely just aesthetic.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
从性能角度来看,演示的代码通过 VC 和 GCC 得到了完全优化。 然而,更好的策略通常是将函子作为参数,这样您可以获得更大的灵活性和相同的性能特征。
From a performance pov the code demonstrated with get completely optimized with both VC and GCC. However, a better strategy often is to take the functor as a parameter, that way you get a lot more flexibility and identical performance characteristics.
我建议定义与 STL 容器一起使用的函子,即它们应该实现operator()。 (遵循您所使用语言的 API 始终是一个好主意。)
这使您的算法非常通用(传入函数、函子、stl-bind、boost::function、boost::bind、boost:: lambda, ...) 这是人们通常想要的。
这样,您不需要指定函子类型作为模板参数,只需构造一个实例并将其传入:
I'd recommend defining functor that work with the STL-containers, i.e. they should implement operator(). (Following the API of the language you're using is always a good idea.)
That allow your algorithms to be very generic (pass in functions, functors, stl-bind, boost::function, boost::bind, boost::lambda, ...) which is what one usually wants.
This way, you don't need to specify the functor type as a template parameter, just construct an instance and pass it in:
在另一个类中实现构造函数似乎没有任何意义。
您所做的只是打破封装并设置您的类以供滥用。
构造函数应该将对象初始化为类定义的良好状态。 您允许另一个对象初始化您的类。 您如何保证该模板类知道如何正确初始化您的类? 您的类的用户可以提供任何可能以非预期方式扰乱对象内部状态的对象。
该类应该是自包含的,并将其自身初始化为良好的状态。 您似乎正在做的就是使用模板只是为了看看它们能做什么。
There does not seem any point in implementing the constructor in another class.
All you are doing is breaking encapsulation and setting up your class for abuse.
The constructor is supposed to initialize the object into a good state as defined by the class. You are allowing another object to initialize your class. What guarantees do you have that this template class knows how to initialize your class correctly? A user of your class can provide any object that could mess with the internal state of your object in ways not intended.
The class should be self contained and initialize itself to a good state. What you seem to be doing is playing with templates just to see what they can do.