C++14stlintermediate
std::get<Type>() for Tuples
C++14 · Modern Refined · Compiler flag: -std=c++14
Explanation
Access tuple elements by their type instead of by index using `std::get<T>()`. Each type in the tuple must be unique for this overload to compile. This makes code more readable and less fragile when tuple layouts change.
Real-World Scenario
A multi-sensor reading is stored as a tuple of distinct measurement types. Retrieving values by type is clearer than remembering positional indices, especially as new sensor channels are added.
Quick Snippet
snippet.cpp
#include <tuple>
#include <iostream>
#include <string>
int main() {
using SensorReading = std::tuple<double, int, std::string>;
SensorReading reading{36.6, 98, "normal"};
double temperature = std::get<double>(reading);
int heart_rate = std::get<int>(reading);
auto& status = std::get<std::string>(reading);
std::cout << "Temp: " << temperature
<< " HR: " << heart_rate
<< " Status: " << status << "\n";
}Full Example
get_type_tuple.cpp
// CodeNebula - C++14 Example: std::get<Type>() for Tuples
// Compile: g++ -std=c++14 -Wall -Wextra -o example get_type_tuple.cpp
// Demonstrates accessing tuple elements by type instead of index using
// std::get<Type>(). The type must appear exactly once in the tuple.
// Real-world use: named-like access to tuple fields, clearer code when
// tuple element types are distinct, and reducing index-based errors.
#include <iostream>
#include <tuple>
#include <string>
#include <utility>
// ------------------------------------------------------------------
// Type aliases for clarity in multi-type tuples
// ------------------------------------------------------------------
struct Name { std::string value; };
struct Age { int value; };
struct Salary { double value; };
int main()
{
// ------------------------------------------------------------------
// 1. Basic get-by-type (each type appears once)
// ------------------------------------------------------------------
auto record = std::make_tuple(42, 3.14, std::string("hello"));
std::cout << "=== Basic get<Type> ===" << std::endl;
std::cout << " get<int> : " << std::get<int>(record) << std::endl;
std::cout << " get<double> : " << std::get<double>(record) << std::endl;
std::cout << " get<string> : " << std::get<std::string>(record) << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 2. Comparison: index-based vs type-based access
// ------------------------------------------------------------------
using Config = std::tuple<std::string, int, bool>;
Config cfg{"localhost", 8080, true};
std::cout << "=== Index vs Type Access ===" << std::endl;
std::cout << " By index: get<0> = " << std::get<0>(cfg) << std::endl;
std::cout << " By type: get<string> = " << std::get<std::string>(cfg) << std::endl;
std::cout << " By index: get<1> = " << std::get<1>(cfg) << std::endl;
std::cout << " By type: get<int> = " << std::get<int>(cfg) << std::endl;
std::cout << " By index: get<2> = " << std::boolalpha << std::get<2>(cfg) << std::endl;
std::cout << " By type: get<bool> = " << std::get<bool>(cfg) << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 3. Modifying through get<Type>
// ------------------------------------------------------------------
std::cout << "=== Modification via get<Type> ===" << std::endl;
std::cout << " Before: port = " << std::get<int>(cfg) << std::endl;
std::get<int>(cfg) = 9090;
std::cout << " After: port = " << std::get<int>(cfg) << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 4. With std::pair (pairs are 2-element tuples)
// ------------------------------------------------------------------
std::pair<std::string, int> item{"widget", 99};
std::cout << "=== get<Type> with std::pair ===" << std::endl;
std::cout << " get<string> : " << std::get<std::string>(item) << std::endl;
std::cout << " get<int> : " << std::get<int>(item) << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 5. Wrapper structs for duplicate underlying types
// ------------------------------------------------------------------
// If you need two ints, wrap them in distinct types:
auto employee = std::make_tuple(Name{"Alice"}, Age{30}, Salary{75000.0});
std::cout << "=== Wrapper Types for Distinct Access ===" << std::endl;
std::cout << " Name : " << std::get<Name>(employee).value << std::endl;
std::cout << " Age : " << std::get<Age>(employee).value << std::endl;
std::cout << " Salary : " << std::get<Salary>(employee).value << std::endl;
std::cout << std::endl;
// ------------------------------------------------------------------
// 6. With const and rvalue references
// ------------------------------------------------------------------
const auto& cfg_ref = cfg;
std::cout << "=== Const Reference Access ===" << std::endl;
std::cout << " const get<string> : " << std::get<std::string>(cfg_ref) << std::endl;
// std::get<std::string>(cfg_ref) = "x"; // Error: const reference
// Move semantics
auto moved = std::get<std::string>(std::make_tuple(std::string("moved!")));
std::cout << " rvalue get<string>: " << moved << std::endl;
return 0;
}
/*
Expected output:
=== Basic get<Type> ===
get<int> : 42
get<double> : 3.14
get<string> : hello
=== Index vs Type Access ===
By index: get<0> = localhost
By type: get<string> = localhost
By index: get<1> = 8080
By type: get<int> = 8080
By index: get<2> = true
By type: get<bool> = true
=== Modification via get<Type> ===
Before: port = 8080
After: port = 9090
=== get<Type> with std::pair ===
get<string> : widget
get<int> : 99
=== Wrapper Types for Distinct Access ===
Name : Alice
Age : 30
Salary : 75000
=== Const Reference Access ===
const get<string> : localhost
rvalue get<string>: moved!
*/
Run command
g++ -std=c++14 -Wall -Wextra -o example get_type_tuple.cpp