----------------
title : C++ 레퍼런스 - std::replace 와 std::replace_if (<algorithm>)
cat_title : replace, replace_if
ref_title : std::replace, replace, std::replace_if, replace_if
path : /C++ Reference/algorithm
publish_date : 2020-09-20
----------------

##@ cpp-ref-start

#@ replace, replace_if

`<algorithm>` 에 정의됨

```cpp-formatted
// 참고로 C++ 20 부터 아래 두 함수는 constexpr 함수.
template <class ForwardIt, class T>
void replace(ForwardIt first, ForwardIt last, const T& old_value,
             const T& new_value);  // (1)

template <class ForwardIt, class UnaryPredicate, class T>
void replace_if(ForwardIt first, ForwardIt last, UnaryPredicate p,
                const T& new_value);  // (2)

template <class ExecutionPolicy, class ForwardIt, class T>
void replace(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
             const T& old_value, const T& new_value);  // (3)

template <class ExecutionPolicy, class ForwardIt, class UnaryPredicate, class T>
void replace_if(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
                UnaryPredicate p, const T& new_value);  // (3)
```

**범위 내에 조건에 맞는 원소들을 새로운 값으로 치환한다.**

`replace` 함수는 `first` 부터 `last` 전 까지의 원소들을 하나씩 확인하면서 조건에 만족할 경우 `new_value` 로 값을 치환한다.

1. 이 경우 원소의 값이 `old_value` 와 일치하는 원소들을 치환하다.
2. 이 경우 `p` 함수에 원소를 전달하였을 때 참을 리턴하는 원소들만 치환한다.
3. 이 함수들의 경우 위와 비슷하지만, 실행 방식을 받을 수 있는데 전달하는 `policy` 의 경우 반드시 `std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>` 를 만족해야 한다.

### 인자들

* `first, last` : 원소들의 범위를 나타내는 반복자. (각각 첫 번째 원소와 마지막 원소 바로 다음을 가리킴)
* `old_value` : 해당 값과 같은 원소들을 치환한다.
* `policy` : 사용할 실행 방식
* `p` : 치환 해야 할 원소를 전달하였을 때 `true` 를 리턴하는 함수. `p(v)` 가 리턴하는 값은 반드시 `bool` 로 변환 가능한 값이어야만 한다. 	참고로 `p` 의 경우 전달받은 원소를 변경하면 안되므로, 반드시 `const&` 나 값 형태로 받아야 한다.
* `new_value` : 사용할 새로운 값

### 리턴값

없음

### 구현 예시

#### replace

```cpp-formatted
template <class ForwardIt, class T>
void replace(ForwardIt first, ForwardIt last, const T& old_value,
             const T& new_value) {
  for (; first != last; ++first) {
    if (*first == old_value) {
      *first = new_value;
    }
  }
}
```

#### replace_if

```cpp-formatted
template <class ForwardIt, class UnaryPredicate, class T>
void replace_if(ForwardIt first, ForwardIt last, UnaryPredicate p,
                const T& new_value) {
  for (; first != last; ++first) {
    if (p(*first)) {
      *first = new_value;
    }
  }
}
```

### 실행 예제

```cpp-formatted
#include <algorithm>
#include <array>
#include <iostream>

int main() {
  std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};

  // s 에 등장하는 모든 8 을 88 로 변경한다.
  std::replace(s.begin(), s.end(), 8, 88);

  for (int a : s) {
    std::cout << a << " ";
  }
  std::cout << '\n';

  // s 에 5 보다 작은 값을 모두 55 로 변경한다.
  std::replace_if(
    s.begin(), s.end(), [](const int& i) { return i < 5; }, 55);
  for (int a : s) {
    std::cout << a << " ";
  }
  std::cout << '\n';
}
```

```exec
5 7 4 2 88 6 1 9 0 3 
5 7 55 55 88 6 55 9 55 55 
```

### 참고 자료

* `replace_copy`, `replace_copy_if` : 범위 내에 조건을 만족하는 원소들을 다른 곳에 복사한 후 치환한다.