namespace std {
template <class T>
const T& max(const T& a, const T& b); // (1) C++03
template <class T>
constexpr const T& max(const T& a, const T& b); // (1) C++14
template <class T, class Compare>
const T& max(const T& a, const T& b, Compare comp); // (2) C++03
template <class T, class Compare>
constexpr const T& max(const T& a, const T& b, Compare comp); // (2) C++14
template <class T>
T max(initializer_list<T> t); // (3) C++11
template <class T>
constexpr T max(initializer_list<T> t); // (3) C++14
template <class T, class Compare>
T max(initializer_list<T> t, Compare comp); // (4) C++11
template <class T, class Compare>
constexpr T max(initializer_list<T> t, Compare comp); // (4) C++14
}
概要
同じ型の2つの値、もしくはinitializer_list
によるN個の値のうち、最大値を取得する。
最後の引数comp
は、2項の述語関数オブジェクトであり、これを使用して比較演算をカスタマイズすることができる。
要件
- 型
T
がoperator<
による比較が可能であること。 initializer_list
バージョンはそれに加えて、要素数が1以上であり、T
がコピーコンストラクト可能であること。
戻り値
最大値
備考
- 等価な要素が 2 つ以上あった場合には、最も左の要素を返す。
- 型
T
がoperator<
による比較が可能であることが要件になっているが、(2) と (4) の形式では当該要件を満たさなくても問題ないものと思われる。
例
#include <cassert>
#include <algorithm>
#include <functional>
int main()
{
int result1 = std::max(2, 3);
assert(result1 == 3);
int result2 = std::max(2, 3, std::greater<int>());
assert(result2 == 2);
int result3 = std::max({1, 2, 3});
assert(result3 == 3);
int result4 = std::max({1, 2, 3}, std::greater<int>());
assert(result4 == 1);
}
xxxxxxxxxx
#include <cassert>
#include <algorithm>
#include <functional>
int main()
{
int result1 = std::max(2, 3);
assert(result1 == 3);
int result2 = std::max(2, 3, std::greater<int>());
assert(result2 == 2);
int result3 = std::max({1, 2, 3});
assert(result3 == 3);
int result4 = std::max({1, 2, 3}, std::greater<int>());
assert(result4 == 1);
}
出力
実装例
template <class T>
const T& max(const T& a, const T& b)
{
return a < b ? b : a;
}
template <class T, class Compare>
const T& max(const T& a, const T& b, Compare comp)
{
return comp(a, b) ? b : a;
}
template <class T>
T max(std::initializer_list<T> t)
{
return *std::max_element(t.begin(), t.end());
}
template <class T, class Compare>
T max(std::initializer_list<T> t, Compare comp)
{
return *std::max_element(t.begin(), t.end(), comp);
}
initializer_listバージョンの使用可能状況
- Clang: ??
- GCC: 4.7.0 ✅
- ICC: ??
- Visual C++: 2013 ✅, 2015 ✅
備考
Windows環境においては、<windows.h>
をインクルードするとmax
という名前の関数マクロが定義され、std::max()
と衝突してしまうという問題がある。
この解決策として以下の2つの方法がある:
<windows.h>
をインクルードするまでに#define NOMINMAX
を行う。これでmax
マクロがdefineされなくなる。std::max()
を呼び出す際に、(std::max)(a, b);
のように関数名をカッコで囲んで使用する。これで、名前解決においてstd::max()
関数が必ず使用される。