Structs, Tuples & std::pair
struct, tuple ও pair
1. struct — Bundling Data
#include <iostream>
#include <string>
struct Point {
double x;
double y;
};
struct Person {
std::string name;
int age;
};
int main() {
Point p{3.0, 4.0};
Person sara{"Sara", 21};
std::cout << p.x << ", " << p.y << "\n";
std::cout << sara.name << " " << sara.age << "\n";
}
struct defaults to public; class defaults to private. Convention: use struct for plain data, class for encapsulated objects.
2. std::pair — Two of Anything
#include <iostream>
#include <utility>
int main() {
std::pair<int, std::string> p{42, "answer"};
std::cout << p.first << " -> " << p.second << "\n";
auto p2 = std::make_pair(3.14, 'a');
std::cout << p2.first << " " << p2.second << "\n";
}
3. std::tuple — Any Number of Things
#include <iostream>
#include <tuple>
#include <string>
int main() {
std::tuple<int, std::string, double> t{1, "x", 3.14};
std::cout << std::get<0>(t) << " "
<< std::get<1>(t) << " "
<< std::get<2>(t) << "\n";
}
4. Structured Bindings (C++17) — The Killer Feature
Decompose a struct, pair, or tuple into named variables in one line:
#include <iostream>
#include <map>
#include <tuple>
std::tuple<int, int, int> stats() { return {3, 5, 7}; }
int main() {
auto [a, b, c] = stats();
std::cout << a << " " << b << " " << c << "\n";
std::map<std::string, int> m = {{"a",1},{"b",2}};
for (const auto& [key, value] : m)
std::cout << key << "=" << value << "\n";
}
5. Aggregate Initialization
For simple structs (no constructors, all public), brace init by member order:
struct Date { int day, month, year; };
Date today{9, 5, 2026};
Date birthday{.day=15, .month=8, .year=2003}; // designated init (C++20)
6. Practice Problems
- Define a struct
Rectanglewith width and height.✨ Show Answer
struct Rectangle { double width, height; }; - Add a method
area()to Rectangle.✨ Show Answer
struct Rectangle { double width, height; double area() const { return width * height; } }; - Return two values (min, max) from a function.
✨ Show Answer
std::pair<int,int> minMax(std::vector<int> v) { return {*std::min_element(v.begin(),v.end()), *std::max_element(v.begin(),v.end())}; } auto [lo, hi] = minMax(v); - Why prefer a struct over a tuple when fields have meaning?
✨ Show Answer
Named fields are self-documenting.
p.firstvsp.x— the latter is clearer. - Structured-bind a map iteration.
✨ Show Answer
for (const auto& [k, v] : m) std::cout << k << ":" << v; - Create a tuple of (string, int, double) and access each.
✨ Show Answer
auto t = std::make_tuple("hi", 3, 2.5); std::cout << std::get<0>(t) << std::get<1>(t) << std::get<2>(t); - Define a struct member with default value.
✨ Show Answer
struct Config { int port = 8080; std::string host = "localhost"; }; - Default-constructed Point — what are x, y?
✨ Show Answer
For non-class members (int, double), value-initialization with
{}gives 0. With no initializer (Point p;), they're indeterminate. - Compare two Points for equality.
✨ Show Answer
struct Point { double x, y; bool operator==(const Point&) const = default; // C++20 }; - Why does std::map use std::pair internally?
✨ Show Answer
Each entry is a key-value pair. Iterating gives
pair<const Key, Value>. - Designated initializer (C++20) example.
✨ Show Answer
Date d{.day=9, .month=5, .year=2026}; - Pass a struct to a function.
✨ Show Answer
double area(const Rectangle& r) { return r.width * r.height; }Pass by const reference for any non-trivial struct.
- Build a vector of structs and find one by criteria.
✨ Show Answer
std::vector<Person> ps = {{"a",20},{"b",30}}; auto it = std::find_if(ps.begin(), ps.end(), [](const Person& p){ return p.age > 25; }); - Why prefer aggregate brace init over old-style assignment?
✨ Show Answer
Brace init catches narrowing conversions and is consistent across all kinds of types (struct, std::pair, std::vector...).
Summary
Use struct when fields have meaning. Use std::pair/std::tuple for
anonymous bundling and multi-return. Structured bindings (C++17) make decomposition trivial.
For a class to behave as a value type, default the comparison operators (C++20).