Abseil Tip 59 튜플 연결하기


title: “Tip of the Week #59: 튜플 연결하기” layout: tips sidenav: side-nav-tips.html published: true permalink: tips/59 type: markdown order: “059” —

처음 게시: 2013-10-21 (totw/59)

작성자: Greg Miller (jgm@google.com)

업데이트: 2018-01-24

“이제 손을 맞잡고, 마음도 함께 나누십시오.” –헨리 6세, 윌리엄 셰익스피어

2013년 3월, 우리는 Tip #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), "-");
// 복사하지 않지만, lvalue에만 작동합니다.
s = absl::StrJoin(std::tie(a, b, c), "-");
// 복사하지 않고, lvalue와 rvalue 모두에 작동합니다.
s = absl::StrJoin(std::forward_as_tuple(123, MakeFoo(), c), "-");

모든 컨테이너를 연결할 때와 마찬가지로, 튜플의 요소는 기본적으로 absl::AlphaNumFormatter를 사용해 포맷됩니다. 하지만 튜플에 기본 포맷터가 처리하지 못하는 요소가 포함되어 있을 경우, 사용자 정의 연결 포맷터를 지정할 수 있습니다. 튜플에 여러 사용자 정의 형식의 요소가 있을 경우, 사용자 정의 Formatter 객체에 여러 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의 유연성을 더욱 높입니다.