Practical difference between a struct with only operator() and a normal function

心已入冬 提交于 2020-08-02 07:51:16

问题


I have seen code that looks like this:

struct foo_functor {
  template <typename T, typename U>
  constexpr auto operator()(T t, U u) const -> decltype(t | u) {
    return t | u;
  }
};

constexpr foo_functor foo;

As far as I can tell, it's the same as the following:

template <typename T, typename U>
constexpr auto foo(T t, U u) -> decltype(t | u) {
  return t | u;
}

Why would you want to do the first one? Are there any differences? As far as I could see from the compiler output, at least with constexpr, there wasn't. What about if they weren't constexpr, would there be any differences in that case?

Edit: As a note, code very similar to the first example was seemingly being used in place of normal functions. 6 different structures, all with only operator() templates, all were instantiated like the last line of the example. Each was then used exactly like a normal function.


回答1:


Someone suggested in the comments that a function object can have additional state. While this is true, I would be a bit more specific: you can create multiple copies of a function object with varying state. If the function object is singleton, then this point is moot; a function can also have state in the form of global variables.

And if your function object is declared constexpr, then none of its internal state can be mutable. This puts it in the same position as a constexpr function: calling it can be a constant expression but only as long as it doesn't access any non-constant-expression global state.

One important difference before C++17 is that functions could be inline, whereas objects could not be. In C++14, if you defined the functor foo in a header, then there would be one copy of it per translation unit. If you needed foo to have the same address in all translation units, you would need to declare it as an inline function. But in C++17, function objects can be inline too.

But even if you only have a single instance of the function object, and it has no state, and you are using C++17 or later, there is still at least one important difference between that and a function: functions can be found by argument-dependent lookup, whereas function objects cannot. This is the reason why some "functions" in the C++20 Ranges library actually cannot be functions at all, and must be function objects. These are informally referred to as niebloids.



来源:https://stackoverflow.com/questions/62093977/practical-difference-between-a-struct-with-only-operator-and-a-normal-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!