// Copyright 2017 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License.
{ // Array of ints constint a[] = {1, 2, 3, -4};
EXPECT_EQ("1-2-3--4", absl::StrJoin(a, a + ABSL_ARRAYSIZE(a), "-"));
}
{ // Collection of pointers int x = 1, y = 2, z = 3;
std::vector<int*> v = {&x, &y, &z};
EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
}
{ // Collection of pointers to pointers int x = 1, y = 2, z = 3; int *px = &x, *py = &y, *pz = &z;
std::vector<int**> v = {&px, &py, &pz};
EXPECT_EQ("1-2-3", absl::StrJoin(v, "-"));
}
{ // Collection of pointers to std::string
std::string a("a"), b("b");
std::vector<std::string*> v = {&a, &b};
EXPECT_EQ("a-b", absl::StrJoin(v, "-"));
}
{ // A std::map, which is a collection of std::pair<>s.
std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
}
{ // Shows absl::StrSplit and absl::StrJoin working together. This example is // equivalent to s/=/-/g. const std::string s = "a=b=c=d";
EXPECT_EQ("a-b-c-d", absl::StrJoin(absl::StrSplit(s, "="), "-"));
}
// // A few examples of edge cases //
{ // Empty range yields an empty string.
std::vector<std::string> v;
EXPECT_EQ("", absl::StrJoin(v, "-"));
}
{ // A range of 1 element gives a string with that element but no // separator.
std::vector<std::string> v = {"foo"};
EXPECT_EQ("foo", absl::StrJoin(v, "-"));
}
{ // A range with a single empty string element
std::vector<std::string> v = {""};
EXPECT_EQ("", absl::StrJoin(v, "-"));
}
{ // A range with 2 elements, one of which is an empty string
std::vector<std::string> v = {"a", ""};
EXPECT_EQ("a-", absl::StrJoin(v, "-"));
}
{ // A range with 2 empty elements.
std::vector<std::string> v = {"", ""};
EXPECT_EQ("-", absl::StrJoin(v, "-"));
}
{ // A std::vector of bool.
std::vector<bool> v = {true, false, true};
EXPECT_EQ("1-0-1", absl::StrJoin(v, "-"));
}
}
TEST(AlphaNumFormatter, FormatterAPI) { // Not an exhaustive test. See strings/strcat_test.h for the exhaustive test // of what AlphaNum can convert. auto f = absl::AlphaNumFormatter();
std::string s;
f(&s, "Testing: ");
f(&s, static_cast<int>(1));
f(&s, static_cast<int16_t>(2));
f(&s, static_cast<int64_t>(3));
f(&s, static_cast<float>(4));
f(&s, static_cast<double>(5));
f(&s, static_cast<unsigned>(6));
f(&s, static_cast<size_t>(7));
f(&s, absl::string_view(" OK"));
EXPECT_EQ("Testing: 1234567 OK", s);
}
// Make sure people who are mistakenly using std::vector<bool> even though // they're not memory-constrained can use absl::AlphaNumFormatter().
TEST(AlphaNumFormatter, VectorOfBool) { auto f = absl::AlphaNumFormatter();
std::string s;
std::vector<bool> v = {true, false, true};
f(&s, *v.cbegin());
f(&s, *v.begin());
f(&s, v[1]);
EXPECT_EQ("110", s);
}
TEST(AlphaNumFormatter, AlphaNum) { auto f = absl::AlphaNumFormatter();
std::string s;
f(&s, absl::AlphaNum("hello"));
EXPECT_EQ("hello", s);
}
// A dummy formatter that wraps each element in parens. Used in some tests // below. struct TestingParenFormatter { template <typename T> voidoperator()(std::string* s, const T& t) {
absl::StrAppend(s, "(", t, ")");
}
};
TEST(PairFormatter, FormatterAPI) {
{ // Tests default PairFormatter(sep) that uses AlphaNumFormatter for the // 'first' and 'second' members. constauto f = absl::PairFormatter("=");
std::string s;
f(&s, std::make_pair("a", "b"));
f(&s, std::make_pair(1, 2));
EXPECT_EQ("a=b1=2", s);
}
{ // Tests using a custom formatter for the 'first' and 'second' members. auto f = absl::PairFormatter(TestingParenFormatter(), "=",
TestingParenFormatter());
std::string s;
f(&s, std::make_pair("a", "b"));
f(&s, std::make_pair(1, 2));
EXPECT_EQ("(a)=(b)(1)=(2)", s);
}
}
TEST(DereferenceFormatter, FormatterAPI) {
{ // Tests wrapping the default AlphaNumFormatter. const absl::strings_internal::DereferenceFormatterImpl<
absl::strings_internal::AlphaNumFormatterImpl>
f; int x = 1, y = 2, z = 3;
std::string s;
f(&s, &x);
f(&s, &y);
f(&s, &z);
EXPECT_EQ("123", s);
}
std::string x = "x";
std::string y = "y";
std::string z = "z";
std::string s;
f(&s, &x);
f(&s, &y);
f(&s, &z);
EXPECT_EQ(s, "xyz");
}
{ // Tests wrapping a custom formatter. auto f = absl::DereferenceFormatter(TestingParenFormatter()); int x = 1, y = 2, z = 3;
std::string s;
f(&s, &x);
f(&s, &y);
f(&s, &z);
EXPECT_EQ("(1)(2)(3)", s);
}
{
absl::strings_internal::DereferenceFormatterImpl<
absl::strings_internal::AlphaNumFormatterImpl>
f; auto x = std::unique_ptr<int>(newint(1)); auto y = std::unique_ptr<int>(newint(2)); auto z = std::unique_ptr<int>(newint(3));
std::string s;
f(&s, x);
f(&s, y);
f(&s, z);
EXPECT_EQ("123", s);
}
}
// // Tests the interfaces for the 4 public Join function overloads. The semantics // of the algorithm is covered in the above APIExamples test. //
TEST(StrJoin, PublicAPIOverloads) {
std::vector<std::string> v = {"a", "b", "c"};
{ // Tests initializer_list of ints with a non-default formatter auto a = {1, 2, 3};
TestingParenFormatter f;
EXPECT_EQ("(1)-(2)-(3)", absl::StrJoin(a, "-", f));
}
}
TEST(StrJoin, StringViewInitializerList) {
{ // Tests initializer_list of string_views
std::string b = "b";
EXPECT_EQ("a-b-c", absl::StrJoin({"a", b, "c"}, "-"));
}
{ // Tests initializer_list of string_views with a non-default formatter
TestingParenFormatter f;
std::string b = "b";
EXPECT_EQ("(a)-(b)-(c)", absl::StrJoin({"a", b, "c"}, "-", f));
}
class NoCopy { public: explicit NoCopy(absl::string_view view) : view_(view) {}
NoCopy(const NoCopy&) = delete; operator absl::string_view() { return view_; } // NOLINT private:
absl::string_view view_;
};
{ // Tests initializer_list of string_views preferred over initializer_list<T> // for T that is implicitly convertible to string_view
EXPECT_EQ("a-b-c",
absl::StrJoin({NoCopy("a"), NoCopy("b"), NoCopy("c")}, "-"));
}
{ // Tests initializer_list of string_views preferred over initializer_list<T> // for T that is implicitly convertible to string_view
TestingParenFormatter f;
EXPECT_EQ("(a)-(b)-(c)",
absl::StrJoin({NoCopy("a"), NoCopy("b"), NoCopy("c")}, "-", f));
}
}
// A minimal value type for `StrJoin` inputs. // Used to ensure we do not excessively require more a specific type, such as a // `string_view`. // // Anything that can be `data()` and `size()` is OK. class TestValue { public:
TestValue(constchar* data, size_t size) : data_(data), size_(size) {} constchar* data() const { return data_; }
size_t size() const { return size_; }
private: constchar* data_;
size_t size_;
};
// A minimal C++20 forward iterator, used to test that we do not impose // excessive requirements on StrJoin inputs. // // The 2 main differences between pre-C++20 LegacyForwardIterator and the // C++20 ForwardIterator are: // 1. `operator->` is not required in C++20. // 2. `operator*` result does not need to be an lvalue (a reference). // // The `operator->` requirement was removed on page 17 in: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1037r0.pdf // // See the `[iterator.requirements]` section of the C++ standard. // // The value type is a template parameter so that we can test the behaviour // of `StrJoin` specializations, e.g. the NoFormatter specialization for // `string_view`. template <typename ValueT> class TestIterator { public: using iterator_category = std::forward_iterator_tag; using value_type = ValueT; using pointer = void; using reference = const value_type&; using difference_type = int;
// `data` must outlive the result. static TestIterator begin(const std::vector<absl::string_view>& data) { return TestIterator(&data, 0);
}
// This deliberately returns a `prvalue`. // The requirement to return a reference was removed in C++20.
value_type operator*() const { return ValueT((*data_)[pos_].data(), (*data_)[pos_].size());
}
// `operator->()` is deliberately omitted. // The requirement to provide it was removed in C++20.
template <typename ValueT> class TestIteratorRange { public: // `data` must be non-null and must outlive the result. explicit TestIteratorRange(const std::vector<absl::string_view>& data)
: begin_(TestIterator<ValueT>::begin(data)),
end_(TestIterator<ValueT>::end(data)) {}
TEST(StrJoin, TestIteratorRequirementsNoFormatter) { const std::vector<absl::string_view> a = {"a", "b", "c"};
// When the value type is string-like (`std::string` or `string_view`), // the NoFormatter template specialization is used internally.
EXPECT_EQ("a-b-c",
absl::StrJoin(TestIteratorRange<absl::string_view>(a), "-"));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.