-2

How does this templated operator() work in reference_wrapper implementation

template <class T>
class reference_wrapper {
public:
  // types
  typedef T type;

  // construct/copy/destroy
  reference_wrapper(T& ref) noexcept : _ptr(std::addressof(ref)) {}
  reference_wrapper(T&&) = delete;
  reference_wrapper(const reference_wrapper&) noexcept = default;

  // assignment
  reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;

  // access
  operator T& () const noexcept { return *_ptr; }
  T& get() const noexcept { return *_ptr; }

here it goes:

  template< class... ArgTypes >
  typename std::result_of<T&(ArgTypes&&...)>::type
    operator() ( ArgTypes&&... args ) const {
    return std::invoke(get(), std::forward<ArgTypes>(args)...);
  }

why do we need operator() anyway? how it works?

what is the return content "result_of::type"?

what is (ArgTypes && ..) ??

invoke(get) ???

this code looks like C++ from another planet :)

private:
  T* _ptr;
};
barney
  • 2,172
  • 1
  • 16
  • 25

1 Answers1

1

why do we need operator() anyway? how it works?

Suppose following context

int foo(int bar)
{
    return bar + 5;
}

int main()
{
    std::reference_wrapper<int(int)> ref = foo;
    ref(5);
}

ref(5) calls operator() of reference wrapper. If it wouldn't be there, it would not work, because user defined conversion wouldn't happen in this case.

operator() returns std::result_of<T&(ArgTypes&&...), which is return value of the function stored and std::invoke call such function and forwards parameters to it.

Zereges
  • 5,139
  • 1
  • 25
  • 49
  • oh wow, so not only the reference_wrapper could encapsulate function, but also with some template magic is capable of expressing the function call with templated parameters forwarding? thats amazing! How did you know it? About the std::result_of, std::invoke, etc. And where I can learn about? I.e. I mean that how I could possibly guess that its allowed to wrap a functions, or even express the return type with this user defined template. Is there big systematic manual? Or its "sacred knowledge"? – barney Jun 29 '16 at 11:30
  • @barney [`std::result_of`](http://en.cppreference.com/w/cpp/types/result_of), [`std::invoke`](http://en.cppreference.com/w/cpp/utility/functional/invoke). Not only this site has explanation of standard classes, there usually is *Possible implementation* section, where you can see how it could be implemented and you can learn a lot from that. – Zereges Jun 29 '16 at 14:20
  • @barney "*thats amazing! How did you know it?*" - See [`std::reference_wrapper`](https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper): "If the stored reference is *Callable*, **std::reference_wrapper is callable with the same arguments**." and [`std::reference_wrapper::operator()`](https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator()): "Calls the *Callable* object, reference to which is stored. **This function is available only if the stored reference points to a *Callable* object**." – Remy Lebeau Oct 09 '20 at 17:06