@@ -58,34 +58,30 @@ void ReplaceAll(std::string& in_out, const std::string& search, const std::strin
5858}
5959
6060/* *
61- * Join a list of items
61+ * Join all container items. Typically used to concatenate strings but accepts
62+ * containers with elements of any type.
6263 *
63- * @param list The list to join
64- * @param separator The separator
65- * @param unary_op Apply this operator to each item in the list
64+ * @param container The items to join
65+ * @param separator The separator
66+ * @param unary_op Apply this operator to each item
6667 */
67- template <typename T, typename BaseType, typename UnaryOp>
68- auto Join (const std::vector<T>& list, const BaseType& separator, UnaryOp unary_op)
69- -> decltype(unary_op(list.at(0 )))
68+ template <typename C, typename S, typename UnaryOp>
69+ auto Join (const C& container, const S& separator, UnaryOp unary_op)
7070{
71- decltype (unary_op (list.at (0 ))) ret;
72- for (size_t i = 0 ; i < list.size (); ++i) {
73- if (i > 0 ) ret += separator;
74- ret += unary_op (list.at (i));
71+ decltype (unary_op (*container.begin ())) ret;
72+ bool first{true };
73+ for (const auto & item : container) {
74+ if (!first) ret += separator;
75+ ret += unary_op (item);
76+ first = false ;
7577 }
7678 return ret;
7779}
7880
79- template <typename T , typename T2 >
80- T Join (const std::vector<T>& list , const T2 & separator)
81+ template <typename C , typename S >
82+ auto Join (const C& container , const S & separator)
8183{
82- return Join (list, separator, [](const T& i) { return i; });
83- }
84-
85- // Explicit overload needed for c_str arguments, which would otherwise cause a substitution failure in the template above.
86- inline std::string Join (const std::vector<std::string>& list, std::string_view separator)
87- {
88- return Join<std::string>(list, separator);
84+ return Join (container, separator, [](const auto & i) { return i; });
8985}
9086
9187/* *
0 commit comments