Search code examples
c++templatesstlreference-wrapper

reference_wrapper implementation details


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;
};

Solution

  • 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.