C++17stladvanced
std::make_from_tuple
C++17 · Practical Modern · Compiler flag: -std=c++17
Explanation
Constructs an object of type `T` by unpacking a tuple as constructor arguments. It is the construction counterpart of `std::apply`, enabling factory patterns that store constructor arguments as tuples.
Real-World Scenario
Implement a deferred object factory that stores construction parameters and creates objects on demand.
Quick Snippet
snippet.cpp
#include <tuple>
struct Connection {
std::string host;
int port;
Connection(std::string h, int p) : host(std::move(h)), port(p) {}
};
auto args = std::make_tuple(std::string("localhost"), 8080);
auto conn = std::make_from_tuple<Connection>(args);Full Example
make_from_tuple.cpp
// CodeNebula - C++17 Example: std::make_from_tuple
// Compile: g++ -std=c++17 -Wall -Wextra -o example make_from_tuple.cpp
// Demonstrates std::make_from_tuple, which constructs an object of type T
// by unpacking a tuple as constructor arguments. This is the construction
// counterpart to std::apply (which calls a callable with tuple args).
#include <iostream>
#include <tuple>
#include <string>
#include <array>
struct Point {
double x, y;
Point(double x, double y) : x(x), y(y) {
std::cout << " Point(" << x << ", " << y << ") constructed" << std::endl;
}
};
struct Person {
std::string name;
int age;
double height;
Person(std::string n, int a, double h)
: name(std::move(n)), age(a), height(h) {}
void print() const {
std::cout << " " << name << ", age " << age
<< ", height " << height << "m" << std::endl;
}
};
struct Widget {
int id;
std::string label;
bool active;
Widget(int i, std::string l, bool a)
: id(i), label(std::move(l)), active(a) {}
void print() const {
std::cout << " Widget #" << id << " \"" << label
<< "\" active=" << active << std::endl;
}
};
// Factory function that creates objects from stored tuple configs
template <typename T, typename Tuple>
T create(const Tuple& args) {
return std::make_from_tuple<T>(args);
}
int main()
{
// ------------------------------------------------------------------
// 1. Basic construction from a tuple
// ------------------------------------------------------------------
std::cout << "=== Basic Construction ===" << std::endl;
auto point_args = std::make_tuple(3.0, 4.0);
auto p = std::make_from_tuple<Point>(point_args);
std::cout << " Result: (" << p.x << ", " << p.y << ")" << std::endl;
// ------------------------------------------------------------------
// 2. Mixed types
// ------------------------------------------------------------------
std::cout << "\n=== Mixed Types ===" << std::endl;
auto person_args = std::make_tuple(std::string("Alice"), 30, 1.68);
auto alice = std::make_from_tuple<Person>(person_args);
alice.print();
// ------------------------------------------------------------------
// 3. Constructing from an inline tuple
// ------------------------------------------------------------------
std::cout << "\n=== Inline Tuple ===" << std::endl;
auto w = std::make_from_tuple<Widget>(
std::make_tuple(42, std::string("gear"), true)
);
w.print();
// ------------------------------------------------------------------
// 4. Using std::array (which is tuple-like)
// ------------------------------------------------------------------
std::cout << "\n=== From std::array ===" << std::endl;
std::array<double, 2> coords = {7.5, 2.3};
auto p2 = std::make_from_tuple<Point>(coords);
std::cout << " Result: (" << p2.x << ", " << p2.y << ")" << std::endl;
// ------------------------------------------------------------------
// 5. Generic factory pattern
// ------------------------------------------------------------------
std::cout << "\n=== Factory Pattern ===" << std::endl;
auto cfg1 = std::make_tuple(std::string("Bob"), 25, 1.80);
auto cfg2 = std::make_tuple(99, std::string("motor"), false);
auto bob = create<Person>(cfg1);
bob.print();
auto motor = create<Widget>(cfg2);
motor.print();
// ------------------------------------------------------------------
// 6. With std::pair (also tuple-like)
// ------------------------------------------------------------------
std::cout << "\n=== From std::pair ===" << std::endl;
std::pair<double, double> xy{1.0, 9.0};
auto p3 = std::make_from_tuple<Point>(xy);
std::cout << " Result: (" << p3.x << ", " << p3.y << ")" << std::endl;
return 0;
}
/*
Expected output:
=== Basic Construction ===
Point(3, 4) constructed
Result: (3, 4)
=== Mixed Types ===
Alice, age 30, height 1.68m
=== Inline Tuple ===
Widget #42 "gear" active=1
=== From std::array ===
Point(7.5, 2.3) constructed
Result: (7.5, 2.3)
=== Factory Pattern ===
Bob, age 25, height 1.8m
Widget #99 "motor" active=0
=== From std::pair ===
Point(1, 9) constructed
Result: (1, 9)
*/
Run command
g++ -std=c++17 -Wall -Wextra -o example make_from_tuple.cpp