每周技巧 #59:连接元组

本节阅读量:

本文翻译自 Abseil 官网的 Tip of the Week #59: Joining Tuples

原文最初作为 totw/59 发布于 2013 年 10 月 21 日。

作者:Greg Miller

更新于 2018 年 1 月 24 日。

“现在牵起你们的手,并用你们的手牵起你们的心。”– Henry VI, William Shakespeare

2013 年 3 月,我们在 技巧 #36 中宣布了新的字符串连接 API。大家对这个新 API 的反馈相当积极,我们也继续努力让它变得更好。功能请求列表中排在最前面的,是连接任意列表的能力,这些列表中可能包含异构数据(我只能假设 Shakespeare 说的是连接一组异构的手和心)。我们没有选择 varargs 或可变参数模板路线,而是添加了对连接 std::tuple 对象的支持,这很好地满足了这个需求。只要创建一个包含异构数据的 std::tupleabsl::StrJoin() 就会像接受任何其他容器一样接受它。下面是几个例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
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), "-");

和连接任何容器一样,tuple 的元素默认使用 absl::AlphaNumFormatter 格式化。不过,如果你的 tuple 包含默认 formatter 无法处理的元素,也可以指定自定义 join Formatter。如果要格式化包含多个自定义元素类型的 tuple,你的自定义 Formatter 对象可以包含多个 operator() 重载。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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 增加了更多灵活性。

每周技巧 #55:名称计数与 unique_ptr

上一节

每周技巧 #61:默认成员初始化器

下一节


本节目录