Index: include/llvm/ADT/StringExtras.h =================================================================== --- include/llvm/ADT/StringExtras.h +++ include/llvm/ADT/StringExtras.h @@ -155,6 +155,8 @@ /// it if it is not printable or if it is an escape char. void PrintEscapedString(StringRef Name, raw_ostream &Out); +namespace detail { + template inline std::string join_impl(IteratorT Begin, IteratorT End, StringRef Separator, std::input_iterator_tag) { @@ -168,25 +170,43 @@ S += (*Begin); } return S; -} + } -template -inline std::string join_impl(IteratorT Begin, IteratorT End, - StringRef Separator, std::forward_iterator_tag) { - std::string S; - if (Begin == End) + template + inline std::string join_impl(IteratorT Begin, IteratorT End, + StringRef Separator, std::forward_iterator_tag) { + std::string S; + if (Begin == End) + return S; + + size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); + for (IteratorT I = Begin; I != End; ++I) + Len += (*Begin).size(); + S.reserve(Len); + S += (*Begin); + while (++Begin != End) { + S += Separator; + S += (*Begin); + } return S; + } - size_t Len = (std::distance(Begin, End) - 1) * Separator.size(); - for (IteratorT I = Begin; I != End; ++I) - Len += (*Begin).size(); - S.reserve(Len); - S += (*Begin); - while (++Begin != End) { - S += Separator; - S += (*Begin); + inline void join_items_impl(std::string &Result, StringRef Separator) {} + + template + inline void join_items_impl(std::string &Result, StringRef Separator, + const Arg &Item) { + Result += Item; + } + + template + inline void join_items_impl(std::string &Result, StringRef Separator, + const Arg1 &A1, const Arg2 &A2, + Args &&... Items) { + Result += A1; + Result += Separator; + join_items_impl(Result, Separator, A2, std::forward(Items)...); } - return S; } /// Joins the strings in the range [Begin, End), adding Separator between @@ -194,7 +214,14 @@ template inline std::string join(IteratorT Begin, IteratorT End, StringRef Separator) { typedef typename std::iterator_traits::iterator_category tag; - return join_impl(Begin, End, Separator, tag()); + return detail::join_impl(Begin, End, Separator, tag()); +} + +template +inline std::string join_items(StringRef Separator, Args &&... Items) { + std::string Result; + detail::join_items_impl(Result, Separator, std::forward(Items)...); + return Result; } } // End llvm namespace Index: unittests/ADT/CMakeLists.txt =================================================================== --- unittests/ADT/CMakeLists.txt +++ unittests/ADT/CMakeLists.txt @@ -53,6 +53,7 @@ SparseBitVectorTest.cpp SparseMultiSetTest.cpp SparseSetTest.cpp + StringExtrasTest.cpp StringMapTest.cpp StringRefTest.cpp TinyPtrVectorTest.cpp