//******************************************************** // The following code example is taken from the book // C++20 - The Complete Guide // by Nicolai M. Josuttis (www.josuttis.com) // http://www.cppstd20.com // // The code is licensed under a // Creative Commons Attribution 4.0 International License // http://creativecommons.org/licenses/by/4.0/ //******************************************************** #include #include #include #include #include // concept for container with push_back(): template concept SupportsPushBack = requires(Coll coll, Coll::value_type val) { coll.push_back(val); }; // concept to disable narrowing conversions: template concept ConvertsWithoutNarrowing = std::convertible_to && requires (From&& x) { { std::type_identity_t{std::forward(x)} } -> std::same_as; }; // add() for single value: template requires ConvertsWithoutNarrowing void add(Coll& coll, const T& val) { if constexpr (SupportsPushBack) { coll.push_back(val); } else { coll.insert(val); } } // add() for multiple values: template requires ConvertsWithoutNarrowing, typename Coll::value_type> void add(Coll& coll, const T& val) { if constexpr (SupportsPushBack) { 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 iVec; add(iVec, 42); // OK: calls push_back() for T being int std::set 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 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 }