본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : std::min, max, equal, any_of, all_of, none_of (98, 11, 17)

by snowoods 2025. 9. 12.

Modern C++

std::min, max, equal, any, all, none

 

개요

C++ 표준 라이브러리는 컨테이너의 원소를 검색하고 비교하는 데 유용한 다양한 알고리즘을 제공합니다. 이 문서에서는 특정 조건을 만족하는 원소를 찾거나, 두 범위를 비교하는 데 사용되는 std::min, std::max, std::equal, std::any_of, std::all_of, std::none_of 함수에 대해 설명합니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++98: std::min, std::max, std::min_element, std::max_element, std::equal
  • C++11: std::any_of, std::all_of, std::none_of
  • C++17: 병렬 실행 정책(std::execution)을 지원하는 알고리즘 오버로드가 추가되었습니다.

 

내용 설명

std::min, std::max, std::min_element, std::max_element

  • std::min, std::max: 두 값 또는 initializer_list 내의 값들 중 가장 작거나 큰 값을 반환합니다.
  • std::min_element, std::max_element: 주어진 범위(range)에서 가장 작거나 큰 원소를 가리키는 반복자(iterator)를 반환합니다.

std::equal

  • 두 개의 범위를 비교하여 모든 원소가 동일한지 확인합니다. 기본적으로 == 연산자를 사용하여 비교하지만, 사용자 정의 비교 함수를 전달할 수도 있습니다.
  • C++17부터 병렬 실행 정책을 지정하여 대량의 데이터를 효율적으로 비교할 수 있습니다.

std::any_of, std::all_of, std::none_of

  • 이 함수들은 주어진 범위의 원소들이 특정 조건을 만족하는지 검사하고 bool 값을 반환합니다.
  • std::all_of: 범위 내의 모든 원소가 조건을 만족하면 true를 반환합니다.
  • std::any_of: 범위 내의 원소 중 하나라도 조건을 만족하면 true를 반환합니다.
  • std::none_of: 범위 내의 어떤 원소도 조건을 만족하지 않으면 true를 반환합니다.

 

예제 코드

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <random>
#include <execution>

namespace
{
    constexpr auto NUM_ELEMENTS = size_t{10U};
};

std::int32_t gen()
{
    static auto seed = std::random_device{};
    static auto g = std::mt19937{seed()};
    static auto d = std::uniform_int_distribution<std::int32_t>{-10, 10};

    return d(g);
}

template <typename T>
void print_vector(const std::string& title, const std::vector<T>& vec)
{
    std::cout << title << ": ";
    for (const auto v : vec)
    {
        std::cout << v << ' ';
    }
    std::cout << '\n';
}

struct Data
{
    std::int32_t v1;
    std::int32_t v2;
};

int main()
{
    auto my_vector = std::vector<std::int32_t>(NUM_ELEMENTS);
    std::generate(my_vector.begin(), my_vector.end(), gen);
    print_vector("Generated Vector", my_vector);

    // std::min_element & std::max_element
    const auto min = std::min_element(my_vector.begin(), my_vector.end());
    const auto max = std::max_element(my_vector.begin(), my_vector.end());
    std::cout << "Min: " << *min << ", Max: " << *max << '\n';

    // std::equal
    const auto my_vector2 = std::vector<Data>{{1, 1}, {2, 3}};
    const auto my_vector3 = std::vector<Data>{{1, 1}, {2, 3}};
    const auto my_vector4 = std::vector<Data>{{1, 1}, {2, 2}};

    const auto eq1 = std::equal(my_vector2.begin(), my_vector2.end(), my_vector3.begin(),
                              [](const auto& i, const auto& j) {
                                  return i.v1 == j.v1 && i.v2 == j.v2;
                              });
    std::cout << "my_vector2 and my_vector3 are equal? " << std::boolalpha << eq1 << '\n';

    const auto eq2 = std::equal(std::execution::par, my_vector2.begin(), my_vector2.end(), my_vector4.begin(),
                              [](const auto& i, const auto& j) {
                                  return i.v1 == j.v1 && i.v2 == j.v2;
                              });
    std::cout << "my_vector2 and my_vector4 are equal? " << std::boolalpha << eq2 << '\n';

    // std::all_of, std::any_of, std::none_of
    auto is_positive = [](int i) { return i > 0; };

    if (std::all_of(my_vector.begin(), my_vector.end(), is_positive))
    {
        std::cout << "All elements are positive." << '\n';
    }

    if (std::any_of(my_vector.begin(), my_vector.end(), is_positive))
    {
        std::cout << "At least one element is positive." << '\n';
    }

    if (std::none_of(my_vector.begin(), my_vector.end(), is_positive))
    {
        std::cout << "No elements are positive." << '\n';
    }

    return 0;
}

 

실행 결과

Generated Vector: -4 8 -9 0 5 2 -1 8 8 -10 
Min: -10, Max: 8
my_vector2 and my_vector3 are equal? true
my_vector2 and my_vector4 are equal? false
At least one element is positive.
  • Generated Vector의 내용은 실행 시마다 달라질 수 있습니다.

 

활용 팁

  • std::min_element, std::max_element는 값이 아닌 반복자를 반환하므로, 실제 값에 접근하려면 역참조(*)가 필요합니다.
  • std::equal 사용 시, 두 번째 범위는 첫 번째 범위의 시작 반복자만 제공하면 됩니다. 단, 두 번째 범위는 첫 번째 범위보다 크거나 같아야 안전합니다.
  • C++17의 병렬 실행 정책은 매우 큰 데이터셋을 처리할 때 성능 향상에 도움이 될 수 있지만, 스레드 생성 및 동기화 오버헤드로 인해 작은 데이터셋에서는 오히려 성능이 저하될 수 있습니다.
  • std::any_of, std::all_of, std::none_of는 조건자(predicate)를 사용하여 복잡한 조건도 간결하게 표현할 수 있어 코드 가독성을 높이는 데 유용합니다.