C++11stlintermediate
std::piecewise_construct (C++11 Addition)
C++11 · Modern Revolution · Compiler flag: -std=c++11
Explanation
A tag constant used to select the piecewise constructor of `std::pair`, which constructs each element from a separate tuple of arguments.
Real-World Scenario
Insert a complex key-value pair into a map where both key and value require multi-argument construction.
Quick Snippet
snippet.cpp
#include <utility>
#include <tuple>
#include <map>
std::map<std::string, std::string> m;
m.emplace(std::piecewise_construct,
std::forward_as_tuple("key"),
std::forward_as_tuple(10, 'x')); // string(10, 'x')Full Example
piecewise_construct.cpp
// CodeNebula - C++11 Example: std::piecewise_construct
// Compile: g++ -std=c++11 -Wall -Wextra -o example piecewise_construct.cpp
// std::piecewise_construct is a tag used with std::pair's constructor
// to forward separate argument tuples to the constructors of each
// element. Essential for in-place construction in maps.
#include <iostream>
#include <utility>
#include <tuple>
#include <map>
#include <string>
struct Point {
double x, y;
Point(double x_, double y_) : x(x_), y(y_) {
std::cout << " Point(" << x << ", " << y << ") constructed" << std::endl;
}
// No default constructor -- must use piecewise_construct
Point(const Point& o) : x(o.x), y(o.y) {
std::cout << " Point copied" << std::endl;
}
};
struct Label {
std::string text;
int priority;
Label(std::string t, int p) : text(std::move(t)), priority(p) {
std::cout << " Label(\"" << text << "\", " << priority << ") constructed" << std::endl;
}
Label(const Label& o) : text(o.text), priority(o.priority) {
std::cout << " Label copied" << std::endl;
}
};
int main() {
// Piecewise construct a pair of complex types
std::cout << "Creating pair with piecewise_construct:" << std::endl;
std::pair<Point, Label> item(
std::piecewise_construct,
std::forward_as_tuple(3.0, 4.0), // args for Point
std::forward_as_tuple("origin", 1) // args for Label
);
std::cout << "Result: Point(" << item.first.x << ", " << item.first.y
<< ") Label(\"" << item.second.text << "\", "
<< item.second.priority << ")\n" << std::endl;
// Primary use case: map::emplace with non-copyable keys or values
std::cout << "Emplacing into map:" << std::endl;
std::map<std::string, Point> locations;
locations.emplace(
std::piecewise_construct,
std::forward_as_tuple("home"),
std::forward_as_tuple(1.0, 2.0)
);
locations.emplace(
std::piecewise_construct,
std::forward_as_tuple("work"),
std::forward_as_tuple(5.0, 6.0)
);
std::cout << "\nMap contents:" << std::endl;
for (const auto& kv : locations) {
std::cout << " " << kv.first << " -> ("
<< kv.second.x << ", " << kv.second.y << ")" << std::endl;
}
// Multi-map with complex key and value
std::cout << "\nMultimap emplace:" << std::endl;
std::multimap<int, Label> tasks;
tasks.emplace(
std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple("urgent task", 10)
);
tasks.emplace(
std::piecewise_construct,
std::forward_as_tuple(2),
std::forward_as_tuple("normal task", 5)
);
std::cout << "\nTasks:" << std::endl;
for (const auto& kv : tasks) {
std::cout << " [" << kv.first << "] " << kv.second.text
<< " (priority " << kv.second.priority << ")" << std::endl;
}
return 0;
}
// Expected output:
// Creating pair with piecewise_construct:
// Point(3, 4) constructed
// Label("origin", 1) constructed
// Result: Point(3, 4) Label("origin", 1)
//
// Emplacing into map:
// Point(1, 2) constructed
// Point(5, 6) constructed
//
// Map contents:
// home -> (1, 2)
// work -> (5, 6)
//
// Multimap emplace:
// Label("urgent task", 10) constructed
// Label("normal task", 5) constructed
//
// Tasks:
// [1] urgent task (priority 10)
// [2] normal task (priority 5)
Run command
g++ -std=c++11 -Wall -Wextra -o example piecewise_construct.cpp