Skip to content

Commit 326b770

Browse files
feat(bigtable): port tuple_utils' (#15532)
* feat(bigtable): port tuple_utils.h * chore: run checkers * chore: add missing files to cmake list
1 parent 77ebc1e commit 326b770

5 files changed

Lines changed: 165 additions & 0 deletions

File tree

google/cloud/bigtable/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ add_library(
215215
internal/rpc_policy_parameters.inc
216216
internal/traced_row_reader.cc
217217
internal/traced_row_reader.h
218+
internal/tuple_utils.h
218219
internal/unary_client_utils.h
219220
metadata_update_policy.cc
220221
metadata_update_policy.h
@@ -464,6 +465,7 @@ if (BUILD_TESTING)
464465
internal/rate_limiter_test.cc
465466
internal/retry_traits_test.cc
466467
internal/traced_row_reader_test.cc
468+
internal/tuple_utils_test.cc
467469
legacy_table_test.cc
468470
metadata_update_policy_test.cc
469471
mocks/mock_row_reader_test.cc

google/cloud/bigtable/bigtable_client_unit_tests.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ bigtable_client_unit_tests = [
6767
"internal/rate_limiter_test.cc",
6868
"internal/retry_traits_test.cc",
6969
"internal/traced_row_reader_test.cc",
70+
"internal/tuple_utils_test.cc",
7071
"legacy_table_test.cc",
7172
"metadata_update_policy_test.cc",
7273
"mocks/mock_row_reader_test.cc",

google/cloud/bigtable/google_cloud_cpp_bigtable.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ google_cloud_cpp_bigtable_hdrs = [
108108
"internal/rpc_policy_parameters.h",
109109
"internal/rpc_policy_parameters.inc",
110110
"internal/traced_row_reader.h",
111+
"internal/tuple_utils.h",
111112
"internal/unary_client_utils.h",
112113
"metadata_update_policy.h",
113114
"mutation_batcher.h",
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_INTERNAL_TUPLE_UTILS_H
16+
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_INTERNAL_TUPLE_UTILS_H
17+
18+
#include "google/cloud/bigtable/version.h"
19+
#include <tuple>
20+
#include <type_traits>
21+
22+
namespace google {
23+
namespace cloud {
24+
namespace bigtable_internal {
25+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
26+
27+
// The implementation for `IsTuple<T>` (below).
28+
template <typename T>
29+
struct IsTupleImpl : std::false_type {};
30+
template <typename... Ts>
31+
struct IsTupleImpl<std::tuple<Ts...>> : std::true_type {};
32+
33+
// Decays the given type `T` and determines whether it is a `std::tuple<...>`.
34+
//
35+
// Example:
36+
//
37+
// using Type = std::tuple<...>;
38+
// static_assert(IsTuple<Type>::value, "");
39+
//
40+
template <typename T>
41+
using IsTuple = IsTupleImpl<std::decay_t<T>>;
42+
43+
// Decays the tuple `T` and returns its size as in the ::value member.
44+
template <typename T>
45+
using TupleSize = std::tuple_size<std::decay_t<T>>;
46+
47+
// Base case of `ForEach` that is called at the end of iterating a tuple.
48+
// See the docs for the next overload to see how to use `ForEach`.
49+
template <std::size_t I = 0, typename T, typename F, typename... Args>
50+
std::enable_if_t<I == TupleSize<T>::value, void> ForEach(T&&, F&&, Args&&...) {}
51+
52+
// This function template iterates the elements of a tuple, calling the given
53+
// functor with each of the tuple's elements as well as any additional
54+
// (optional) caller-provided arguments. The given functor should be able to
55+
// accept each type in the container. All arguments are perfect-forwarded to
56+
// the functor, so the functor may choose to accept the tuple arguments by
57+
// value, const-ref, or even non-const reference, in which case the elements
58+
// inside the tuple may be modified.
59+
//
60+
// Example:
61+
//
62+
// struct Stringify {
63+
// template <typename T>
64+
// void operator()(T& t, std::vector<std::string>& out) const {
65+
// out.push_back(std::to_string(t));
66+
// }
67+
// };
68+
// auto tup = std::make_tuple(true, 42);
69+
// std::vector<std::string> v;
70+
// internal::ForEach(tup, Stringify{}, v);
71+
// EXPECT_THAT(v, testing::ElementsAre("1", "42"));
72+
//
73+
template <std::size_t I = 0, typename T, typename F, typename... Args>
74+
std::enable_if_t<(I < TupleSize<T>::value), void> ForEach(T&& t, F&& f,
75+
Args&&... args) {
76+
auto&& e = std::get<I>(std::forward<T>(t));
77+
std::forward<F>(f)(std::forward<decltype(e)>(e), std::forward<Args>(args)...);
78+
ForEach<I + 1>(std::forward<T>(t), std::forward<F>(f),
79+
std::forward<Args>(args)...);
80+
}
81+
82+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
83+
} // namespace bigtable_internal
84+
} // namespace cloud
85+
} // namespace google
86+
87+
#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_INTERNAL_TUPLE_UTILS_H
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/bigtable/internal/tuple_utils.h"
16+
#include <gmock/gmock.h>
17+
#include <string>
18+
#include <vector>
19+
20+
namespace google {
21+
namespace cloud {
22+
namespace bigtable_internal {
23+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
24+
25+
using ::testing::ElementsAre;
26+
27+
TEST(TupleUtils, IsTuple) {
28+
using T0 = std::tuple<>;
29+
static_assert(IsTuple<T0>::value, "");
30+
static_assert(IsTuple<T0 const>::value, "");
31+
static_assert(IsTuple<T0 const&>::value, "");
32+
33+
using T1 = std::tuple<int>;
34+
static_assert(IsTuple<T1>::value, "");
35+
static_assert(IsTuple<T1 const>::value, "");
36+
static_assert(IsTuple<T1 const&>::value, "");
37+
38+
using TN = std::tuple<int, bool, char>;
39+
static_assert(IsTuple<TN>::value, "");
40+
static_assert(IsTuple<TN const>::value, "");
41+
static_assert(IsTuple<TN const&>::value, "");
42+
43+
static_assert(!IsTuple<int>::value, "");
44+
static_assert(!IsTuple<char>::value, "");
45+
static_assert(!IsTuple<std::vector<int>>::value, "");
46+
}
47+
48+
// Helper functor used to test the `ForEach` function. Uses a templated
49+
// `operator()`.
50+
struct Stringify {
51+
template <typename T>
52+
void operator()(T const& t, std::vector<std::string>& out) const {
53+
out.push_back(std::to_string(t));
54+
}
55+
};
56+
57+
TEST(TupleUtils, ForEachMultipleTypes) {
58+
auto tup = std::make_tuple(true, 42);
59+
std::vector<std::string> v;
60+
ForEach(tup, Stringify{}, v);
61+
EXPECT_THAT(v, ElementsAre("1", "42"));
62+
}
63+
64+
TEST(TupleUtils, ForEachMutate) {
65+
auto add_one = [](int& x) { x += 1; };
66+
auto tup = std::make_tuple(1, 2, 3);
67+
ForEach(tup, add_one);
68+
EXPECT_EQ(tup, std::make_tuple(2, 3, 4));
69+
}
70+
71+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
72+
} // namespace bigtable_internal
73+
} // namespace cloud
74+
} // namespace google

0 commit comments

Comments
 (0)