The following code example is taken from the book
C++20 - The Complete Guide
by Nicolai M. Josuttis,
Leanpub, 2021
The code is licensed under a
Creative Commons Attribution 4.0 International License.
// raw code
#include <iostream>
#include <vector>
#include <set>
#include <ranges>
#include <atomic>
// concept for container with push_back():
template<typename Coll>
concept SupportsPushBack = requires(Coll coll, Coll::value_type val) {
coll.push_back(val);
};
// concept to disable narrowing conversions:
template<typename From, typename To>
concept ConvertsWithoutNarrowing =
std::convertible_to<From, To> &&
requires (From&& x) {
{ std::type_identity_t<To[]>{std::forward<From>(x)} }
-> std::same_as<To[1]>;
};
// add() for single value:
template<typename Coll, typename T>
requires ConvertsWithoutNarrowing<T, typename Coll::value_type>
void add(Coll& coll, const T& val)
{
if constexpr (SupportsPushBack<Coll>) {
coll.push_back(val);
}
else {
coll.insert(val);
}
}
// add() for multiple values:
template<typename Coll, std::ranges::input_range T>
requires ConvertsWithoutNarrowing<std::ranges::range_value_t<T>,
typename Coll::value_type>
void add(Coll& coll, const T& val)
{
if constexpr (SupportsPushBack<Coll>) {
coll.insert(coll.end(),
std::ranges::begin(val), std::ranges::end(val));
}
else {
coll.insert(std::ranges::begin(val), std::ranges::end(val));
}
}
int main()
{
std::vector<int> iVec;
add(iVec, 42); // OK: calls push_back() for T being int
std::set<int> iSet;
add(iSet, 42); // OK: calls insert() for T being int
short s = 42;
add(iVec, s); // OK: calls push_back() for T being short
long long ll = 42;
//add(iVec, ll); // ERROR: narrowing
//add(iVec, 7.7); // ERROR: narrowing
std::vector<double> dVec;
add(dVec, 0.7); // OK: calls push_back() for floating-point types
add(dVec, 0.7f); // OK: calls push_back() for floating-point types
//add(dVec, 7); // ERROR: narrowing
// insert collections:
add(iVec, iSet); // OK: insert set elements into a vector
add(iSet, iVec); // OK: insert vector elements into a set
// can even insert raw array:
int vals[] = {0, 8, 18};
add(iVec, vals); // OK
//add(dVec, vals); // ERROR: narrowing
}