#include #include #include #include #include using namespace std; template auto join_helper(T const& lhs, U const& rhs, int) -> vector { using join_pair = pair; vector result {}; auto lhs_it { begin(lhs) }; auto rhs_it { begin(rhs) }; while (lhs_it != end(lhs) && rhs_it != end(rhs)) { result.emplace_back(*lhs_it, *rhs_it); ++lhs_it; ++rhs_it; } return result; } template auto join_helper(T const& lhs, U const& rhs, float) -> vector { using join_pair = pair; vector result {}; for (auto&& e : lhs) { result.emplace_back(e, rhs); } return result; } template auto join_helper(T const& lhs, U const& rhs, float) -> vector { using join_pair = pair; vector result {}; for (auto&& e : rhs) { result.emplace_back(lhs, e); } return result; } template auto join(T const& lhs, U const& rhs) { return join_helper(lhs, rhs, 0); } int main() { { vector v { 1, -2, 3 }; string s { "hello world" }; auto res = join(v, s); assert( (res == vector>{ {1, 'h'}, {-2, 'e'}, {3, 'l'} }) ); } { list l { "hello", "there" }; int x { 3 }; auto left = join(l, x); assert( (left == vector>{ {"hello", 3}, {"there", 3} }) ); auto right = join(x, l); assert( (right == vector>{ {3, "hello"}, {3, "there"} }) ); } } // Explain what C++20 Concepts are and how they could have been used // to simplify the implementation of join. // C++20 concepts are a new type of entity in the language that // encapsulates requirements on data types. This is used to apply // these requirements on template type paramaters. This was previously // done with a combination of SFINAE, function overload resolution and // template parameter specializations. // This problem would have been a lot easier to implement as well as // easier to understand with the help of C++20 concepts. Primarily // because we can use C++20 concepts to apply requirements to detect // containers. For example: // template // concept Container = requires (T t) { // std::begin(t); // std::end(t); // typename T::value_type value; // }; // template // auto join(LHS const& lhs, RHS const& rhs); // template // auto join(LHS const& lhs, RHS const& rhs); // template // auto join(LHS const& lhs, RHS const& rhs); // This way we don't have to use expression SFINAE, nor do we have to // introduce a priority.