std::identity (C++20 で導入) は、 operator() が引数を変更せずに返す関数オブジェクトです。
注
<utility> のMicrosoft固有の identity 構造体は非推奨であり、以降のバージョンのVisual Studioでは使用できません。 C++20 以降では、代わりに <functional> のstd::identityを使用します。これは、以下で説明する標準準拠の同等の機能です。
std::identity (C++20)
多くの標準ライブラリ API は、プロジェクションや変換関数などの呼び出し可能な引数を受け取ります。 呼び出し可能な呼び出し可能な値を渡す必要があるが、データを変更したくない場合は、 std::identity渡します。 これは範囲アルゴリズムで一般的です。 多くの <algorithm> 範囲のオーバーロードには、既定で std::identity{} に設定されたプロジェクション パラメーターがあります。
構文
struct identity
{
template <class T>
_NODISCARD constexpr T&& operator()(T&& t) const noexcept;
using is_transparent = int;
};
解説
is_transparentメンバー型は、std::identityを透過的な関数オブジェクトとしてマークするタグです。 その存在は、最初に型を共通の形式に変換しなくても、アルゴリズムが比較またはプロジェクションを実行できることを示します。 これは、異種参照をサポートする連想コンテナーとアルゴリズムに役立ち、一時オブジェクトを構築せずにさまざまな型を直接比較できます。
例示
#include <algorithm>
#include <functional>
#include <iostream>
#include <ranges>
#include <vector>
int main()
{
std::vector<int> v{3, 1, 4, 1, 5, 9, 2, 6};
// Ranges algorithms can apply a projection before comparison.
// But if you don't want to apply a projection, i.e. you don't want to modify the data
// before comparison, you can use std::identity to leave each element unchanged.
// Here, std::identity{} means "project each element as itself".
// So the comparator sees the original int values unchanged.
std::ranges::sort(v, std::less{}, std::identity{});
// This call is equivalent because std::identity{} is the default projection.
// In both calls, elements are sorted directly; no field extraction or
// value transformation happens first.
std::ranges::sort(v);
for (int n : v)
{
std::cout << n << ' ';
}
std::cout << '\n';
// Output: 1 1 2 3 4 5 6 9
}
次の使用例は、std::string_view キーを使用してstd::vector<std::string>を検索します。
std::identityにはis_transparentメンバーがあるため、アルゴリズムはこれらの型を直接比較することを認識しています。 このように、キーは比較を行うためだけに一時的な std::string に変換されません。
#include <algorithm>
#include <functional>
#include <iostream>
#include <ranges>
#include <string>
#include <string_view>
#include <vector>
int main()
{
std::vector<std::string> words{"apple", "banana", "cherry", "date"};
std::string_view key = "cherry";
// `std::less<>` is transparent, so it can compare `std::string` and
// `std::string_view` directly.
// `std::identity` is also marked transparent (`is_transparent`), so the
// projection stays type-flexible instead of forcing one fixed type.
auto it = std::ranges::lower_bound(words, key, std::less<>{}, std::identity{});
if (it != words.end() && *it == key)
{
std::cout << "Found: " << *it << '\n';
}
}