作为totw/59最初始发表于2013年10月21日
由Greg Miller(jgm@google.com)创作
更新于2018年1月4日
“现在合起你的双手,然后和你的心在一起.”——亨利六世,威廉.莎士比亚
在2013年3月,我们宣布了在贴士#36中的新的字符串连接API。针对新的API的反馈是相当积极的,接着我们着手工作让这个API变得更好。特性需要列表中优先项是能够连接任意可能不一致的数据列表(我仅能假设莎士比亚所指的是连接手和心的不同集合)。我们不能使用可变参数或可变参数模板,但是我们的确支持连接std::tuple对象,这很好地解决了此需求。简单地创建一个包括你的不一致数据的std::tuple,然后absl::StrJoin()就会像任意其他容器一样接受它。这里有一些示例:
auto tup = std::make_tuple(123, "abc", 0.456);
std::string s = absl::StrJoin(tup, "-");
s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
int a = 123;
std::string b = "abc";
double c = 0.456;
// 生效,但是会拷贝所有参数
s = absl::StrJoin(std::make_tuple(a, b, c), "-");
// 没有拷贝,但是仅对左值生效
s = absl::StrJoin(std::tie(a, b, c), "-");
// 没有拷贝,并且对左值和右值都生效
s = absl::StrJoin(std::forward_as_tuple(123, MakeFoo(), c), "-");
正如连接任意容器一样,元组中的元素默认会使用absl::AlphaNumFormatter来格式化,但是如果你的元组中的元素没有使用默认的格式化来处理,那么你能够指定一个自定义的连接格式化程序。为了格式化一组多个自定义元素类型,你的自定义格式化对象可以包括operator()的多个重载。
例如:
struct Foo {};
struct Bar {};
struct MyFormatter {
void operator()(string* out, const Foo& f) const {
out->append("Foo");
}
void operator()(string* out, const Bar& b) const {
out->append("Bar");
}
};
std::string s = absl::StrJoin(std::forward_as_tuple(Foo(), Bar()), "-",
MyFormatter());
EXPECT_EQ(s, "Foo-Bar");
Absl::StrJoin()API的目标是使用直观且一致的语法来连接任意集合、范围、列表或数据组。我们认为连接std::tuple对象更好地满足了这个目标,并且为这个API添加了更多灵活性。