<utility>
The <utility>
header is part of the C++ Standard Library that provides a collection of utility components. This header contains several useful templates and functions that are widely used in C++ programming. The most notable feature of this header is the std::pair
class template, but it also includes other utilities like std::swap
, std::move
, and std::forward
.
std::pair
class template for storing two heterogeneous objects as a single unitstd::make_pair
function for creating pair objectsstd::swap
for exchanging values of two objectsstd::move
and std::forward
for supporting move semantics and perfect forwardingstd::integer_sequence
and related utilities (since C++14)std::piecewise_construct
for pair constructionstd::pair
and std::make_pair
#include <utility>
#include <iostream>
#include <string>
int main() {
// Creating a pair using the constructor
std::pair<std::string, int> person1("Alice", 30);
// Creating a pair using make_pair
auto person2 = std::make_pair("Bob", 25);
// Accessing pair elements
std::cout << "Person 1: " << person1.first << ", " << person1.second << " years old" << std::endl;
std::cout << "Person 2: " << person2.first << ", " << person2.second << " years old" << std::endl;
// Using structured binding (C++17)
auto [name, age] = person1;
std::cout << "Name: " << name << ", Age: " << age << std::endl;
return 0;
}
std::pair
constructor and std::make_pair
..first
and .second
.std::swap
and Custom Swap Functions#include <utility>
#include <iostream>
#include <vector>
class MyClass {
public:
MyClass(int val) : value(val) {}
int getValue() const { return value; }
// Custom swap function
friend void swap(MyClass& a, MyClass& b) noexcept {
std::cout << "Custom swap called" << std::endl;
std::swap(a.value, b.value);
}
private:
int value;
};
int main() {
int a = 5, b = 10;
std::cout << "Before swap: a = " << a << ", b = " << b << std::endl;
std::swap(a, b);
std::cout << "After swap: a = " << a << ", b = " << b << std::endl;
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {4, 5, 6};
std::cout << "Before swap: vec1[0] = " << vec1[0] << ", vec2[0] = " << vec2[0] << std::endl;
std::swap(vec1, vec2);
std::cout << "After swap: vec1[0] = " << vec1[0] << ", vec2[0] = " << vec2[0] << std::endl;
MyClass obj1(100), obj2(200);
std::cout << "Before swap: obj1 = " << obj1.getValue() << ", obj2 = " << obj2.getValue() << std::endl;
std::swap(obj1, obj2);
std::cout << "After swap: obj1 = " << obj1.getValue() << ", obj2 = " << obj2.getValue() << std::endl;
return 0;
}
std::swap
is used to exchange values of built-in types and standard containers.swap
function is defined for MyClass
to demonstrate ADL (Argument-Dependent Lookup).swap
is called when std::swap
is used on MyClass
objects.std::move
#include <utility>
#include <iostream>
#include <vector>
#include <string>
class Resource {
public:
Resource(const std::string& s) : data(s) {
std::cout << "Constructor called for " << data << std::endl;
}
Resource(const Resource& other) : data(other.data) {
std::cout << "Copy constructor called for " << data << std::endl;
}
Resource(Resource&& other) noexcept : data(std::move(other.data)) {
std::cout << "Move constructor called for " << data << std::endl;
}
~Resource() {
std::cout << "Destructor called for " << data << std::endl;
}
private:
std::string data;
};
int main() {
std::vector<Resource> resources;
std::cout << "Adding Resource without move:" << std::endl;
Resource r1("Resource 1");
resources.push_back(r1);
std::cout << "\nAdding Resource with move:" << std::endl;
Resource r2("Resource 2");
resources.push_back(std::move(r2));
std::cout << "\nEnd of main" << std::endl;
return 0;
}
Resource
class with both copy and move constructors.std::move
is used to invoke the move constructor, avoiding unnecessary copying.std::forward
#include <utility>
#include <iostream>
#include <string>
template<typename T>
void printType(T&& t) {
std::cout << "T is " << (std::is_lvalue_reference<T>::value ? "lvalue" : "rvalue") << std::endl;
}
template<typename T>
void perfectForward(T&& t) {
std::cout << "Forwarding: ";
printType(std::forward<T>(t));
}
int main() {
int x = 10;
const int cx = 20;
std::cout << "Forwarding lvalue:" << std::endl;
perfectForward(x);
std::cout << "Forwarding const lvalue:" << std::endl;
perfectForward(cx);
std::cout << "Forwarding rvalue:" << std::endl;
perfectForward(5);
std::cout << "Forwarding string literal:" << std::endl;
perfectForward("hello");
return 0;
}
std::forward
is used to implement perfect forwarding in template functions.std::integer_sequence
#include <utility>
#include <iostream>
#include <array>
template<typename T, T... Ints>
void printSequence(std::integer_sequence<T, Ints...> int_seq) {
std::cout << "Sequence size: " << int_seq.size() << std::endl;
std::cout << "Values: ";
((std::cout << Ints << ' '), ...);
std::cout << std::endl;
}
template<typename T, std::size_t N, std::size_t... I>
void printArrayImpl(const std::array<T, N>& arr, std::index_sequence<I...>) {
((std::cout << arr[I] << ' '), ...);
std::cout << std::endl;
}
template<typename T, std::size_t N>
void printArray(const std::array<T, N>& arr) {
printArrayImpl(arr, std::make_index_sequence<N>{});
}
int main() {
printSequence(std::integer_sequence<int, 1, 2, 3, 4, 5>{});
printSequence(std::make_integer_sequence<int, 5>{});
printSequence(std::make_index_sequence<5>{});
std::array<int, 5> arr = {10, 20, 30, 40, 50};
std::cout << "Array contents: ";
printArray(arr);
return 0;
}
std::integer_sequence
is used to create compile-time integer sequences.std::make_integer_sequence
and std::make_index_sequence
are utility functions to create sequences.Move Semantics: std::move
doesn't actually move anything; it casts its argument to an rvalue reference, enabling move semantics.
Perfect Forwarding: std::forward
is crucial for implementing perfect forwarding in template functions, preserving value categories.
Pair Comparison: <utility>
provides comparison operators for pairs, which compare first elements and then second elements.
C++17 Additions: C++17 added std::as_const
for obtaining a const reference to an object.
Performance: Using std::move
and std::forward
correctly can lead to significant performance improvements by avoiding unnecessary copies.
The <utility>
header in C++ provides a collection of utility components that are fundamental to many C++ programming tasks:
std::pair
and std::make_pair
for creating and manipulating pairs of values.std::swap
for efficiently exchanging values between objects.std::move
for enabling move semantics, crucial for optimizing resource management.std::forward
for implementing perfect forwarding in template functions.std::integer_sequence
and related utilities for compile-time integer sequences.These utilities are essential for modern C++ programming, enabling efficient and flexible code. They are particularly important in template metaprogramming, optimizing resource management, and implementing generic algorithms.
The components in <utility>
are designed to work seamlessly with other parts of the C++ Standard Library, making them invaluable tools in a C++ programmer's toolkit. Understanding and correctly using these utilities can lead to more efficient, expressive, and maintainable code.