函子类在构造函数中工作

发布于 2024-07-15 03:00:40 字数 766 浏览 7 评论 0原文

我使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

成熟稳重的好男人 2024-07-22 03:00:40

有什么缺点吗?

  • Ctor 不返回任何有用的值——不能在链式调用中使用(例如 foo(bar()))。
  • 它们可以抛出异常。
  • 设计观点——ctor 是对象创建函数,并不是真正的主力。

Any disadvantage?

  • Ctors do not return any useful value -- cannot be used in chained calls (e.g. foo(bar()).
  • They can throw.
  • Design point of view -- ctors are object creation functions, not really meant to be workhorses.
聆听风音 2024-07-22 03:00:40
  1. 编译器实际上内联了Operation的空构造函数(至少在类似情况下gcc会这样做,除非您关闭优化)
  2. 在构造函数中执行所有操作的缺点是您无法以这种方式创建具有某些内部状态的函子 - 例如。 用于计算满足谓词的元素数量的函子。 此外,使用真实对象的方法作为函子可以让您存储它的实例以供以后执行,这是您的构造函数方法无法做到的。
  1. Compilers actually inline the empty constructor of Operation (at least gcc in similar situations does, except when you turned off optimization)
  2. The disadvantage of doing everything in the constructor is that you cannot create a functor with some internal state this way - eg. functor for counting the number of elements satisfying a predicate. Also, using a method of a real object as a functor allows you to store the instance of it for later execution, something you cannot do with your constructor approach.
盛装女皇 2024-07-22 03:00:40

从性能角度来看,演示的代码通过 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.

孤云独去闲 2024-07-22 03:00:40

我建议定义与 STL 容器一起使用的函子,即它们应该实现operator()。 (遵循您所使用语言的 API 始终是一个好主意。)

这使您的算法非常通用(传入函数、函子、stl-bind、boost::function、boost::bind、boost:: lambda, ...) 这是人们通常想要的。

这样,您不需要指定函子类型作为模板参数,只需构造一个实例并将其传入:

my_algorithm(foo, bar, MyOperation())

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:

my_algorithm(foo, bar, MyOperation())
乱了心跳 2024-07-22 03:00:40

在另一个类中实现构造函数似乎没有任何意义。
您所做的只是打破封装并设置您的类以供滥用。

构造函数应该将对象初始化为类定义的良好状态。 您允许另一个对象初始化您的类。 您如何保证该模板类知道如何正确初始化您的类? 您的类的用户可以提供任何可能以非预期方式扰乱对象内部状态的对象。

该类应该是自包含的,并将其自身初始化为良好的状态。 您似乎正在做的就是使用模板只是为了看看它们能做什么。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文