# Way to C++: 5. Forwarding Reference

# 前言

假如有一個函數，可以吃下 Int 和 Char 的 l-value 和 r-value 作為參數

```cpp
void foo(int&& a) {  
    printf("R-Int: %d\n", a);  
}

void foo(char&& c) {  
    printf("R-Char: %c\n", c);  
}

void foo(const int& a) {  
    printf("L-Int: %d\n", a);  
}

void foo(const char& c) {  
    printf("L-Char: %c\n", c);  
}
```

並且，我們希望可以再呼叫這個函數之前先 log 一下，但是當我們嘗試實作時，就會產生疑問：

```cpp
template<typename T>  
void CallFoo(??? val) {  
  printf("Call foo!\\n");  
  foo(val);  
}
```

`???`到底該怎麼填？ `val` 可以是 r-value ，不可以填 `T&` 。

# Forwarding Reference

為了能夠承接下 l-value 和 r-value ，我們要使用 T&& 做為模板型別。而這就是 **Forwarding Reference**。

```cpp
template<typename T>  
void CallFoo(T&& val) {  
    printf("Call foo!\\n");  
    foo(val); // 這也有問題  
}
```

他會把 l-value 和 r-value 好好的傳遞成 l-value 和 r-value。Example:

1.  `CallFoo(1)` : r-value
2.  `CallFoo(x)` : l-value

但假如只有這樣，仍然是有**問題**的。因為在 `Foo` 裡面，直接使用 val 仍然會被視作 l-value 去呼叫 `foo` 。

## std::forward

這函數就是為了這種情況誕生的，它可以把 l-value, r-value 送到該有的地方。

```cpp
template<typename T>  
void CallFoo(T&& val) {  
    printf("Call foo!\\n");  
    foo(std::forward<T>(val));  
}
```

