Perfect forwarding
Tags: blogging, moderncplusplus
Published: 2022-08-13 00:00:00

---
title: Perfect forwarding
date: "2022-08-13"
toc: true
published: true
tags:
  - blogging
  - moderncplusplus
---

# Perfect forwarding

![cover](https://images.unsplash.com/photo-1592739212768-2f4726c714de?utm_medium=medium&w=700&q=50&auto=format)

What is meant by perfect forwarding?

"Forwarding" is the process where one function *forwards* its parameter to another function.
When it is perfect, the function should receive the same object passed from the function that does the forwarding.

In other words, perfect forwarding means we do not just forward objects, we also forward their salient properties, whether they are lvalues or rvalues, const or volatile. 

Do not worry too much about the definition, we will go through some simple examples.

Let say we have a simple class as below

```
class Object {
 public:
  Object() = default;

  void SetName(const std::string &name) { name_ = std::move(name); }
  std::string GetName() const { return name_; }

 private:
  std::string name_;
};
```

We have also few overloaded functions named `UseObject`

```
void UseObject(Object &) {
  std::cout << "calling UseObject(Object &)" << std::endl;
}

void UseObject(const Object &) {
  std::cout << "calling UseObject(const Object &)" << std::endl;
}

void UseObject(Object &&) {
  std::cout << "calling UseObject(Object &&)" << std::endl;
}
```

Now we have the main

```
int main() {
  Object object;
  const Object const_object;
  UseObject(object);
  UseObject(const_object);
  UseObject(std::move(object));
}
```

which would produce the output as below

```
calling UseObject(Object &)
calling UseObject(const Object &)
calling UseObject(Object &&)
```

Right now, let say we have a simple template function that tries to pass the argument to `UseObject` function

```
template <typename T>
void NotForwardToUseObject(T x) {
  UseObject(x);
}
```

Now, running of code

```
int main() {
  Object object;
  const Object const_object;
  NotForwardToUseObject(object);
  NotForwardToUseObject(const_object);
  NotForwardToUseObject(std::move(object));
}
```

would result in 

```
calling UseObject(Object &)
calling UseObject(Object &)
calling UseObject(Object &)
```

where functions are not called accordingly as what we have expected earlier.

This is due to the `const` and `rvalueness` being ignored by the template deduction for `void NotForwardToUseObject(T x)` .

To deal with reference parameters, we have to use universal references, because only universal reference parameters encode information about the lvalueness and rvalueness of the arguments that are passed to them.

Now if we use universal reference for template argument, 

```
template <typename T>
void HalfForwardToUseObject(T &&x) {  // universal reference
  UseObject(x);
}
```

Running of code

```
int main() {
  Object object;
  const Object const_object;
  HalfForwardToUseObject(object);
  HalfForwardToUseObject(const_object);
  HalfForwardToUseObject(std::move(object));
}
```

would result in 

```
calling UseObject(Object &)
calling UseObject(const Object &)
calling UseObject(Object &)
```

Almost! Forwarding of `const` seems working but `rvalueness` of the argument still not getting forwarded correctly.

To have a true perfect forwarding, we have to cast `x` to its original type and lvalue- or r-value-ness

```
template <typename T>
void ForwardToUseObject(T &&x) {
  UseObject(static_cast<T &&>(x));
}
```

Now, running of code

```
int main() {
  Object object;
  const Object const_object;
  ForwardToUseObject(object);
  ForwardToUseObject(const_object);
  ForwardToUseObject(std::move(object));
}
```

would result in 

```
calling UseObject(Object &)
calling UseObject(const Object &)
calling UseObject(Object &&)
```

Perfect! We have successfully passed the object properly.
To simplify the code, we can use `std::forward` from C++ `<utility>` library, 

```
template <typename T>
void PerfectForwardToUseObject(T &&x) {
  UseObject(std::forward<T>(x));
}
```

I hope with the examples above, now you have understand what is meant by perfect forwarding.
As usual, the code above is accessible from my [github](https://github.com/pllee4/blog-public/tree/master/posts/003/files)

Thanks for reading till the end of the post!