// Copyright 2019 Google LLC // // 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 // // http://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. #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_INTERNAL_TUPLE_UTILS_H #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_INTERNAL_TUPLE_UTILS_H #include "google/cloud/spanner/version.h" #include #include namespace google { namespace cloud { namespace spanner { inline namespace SPANNER_CLIENT_NS { namespace internal { // The implementation for `IsTuple` (below). template struct IsTupleImpl : std::false_type {}; template struct IsTupleImpl> : std::true_type {}; // Decays the given type `T` and determines whether it is a `std::tuple<...>`. // // Example: // // using Type = std::tuple<...>; // static_assert(IsTuple::value, ""); // template using IsTuple = IsTupleImpl::type>; // Decays the tuple `T` and returns its size as in the ::value member. template using TupleSize = std::tuple_size::type>; // Base case of `ForEach` that is called at the end of iterating a tuple. // See the docs for the next overload to see how to use `ForEach`. template typename std::enable_if::value, void>::type ForEach( T&&, F&&, Args&&...) {} // This function template iterates the elements of a tuple, calling the given // functor with each of the tuple's elements as well as any additional // (optional) caller-provided arguments. The given functor should be able to // accept each type in the container. All arguments are perfect-forwarded to // the functor, so the functor may choose to accept the tuple arguments by // value, const-ref, or even non-const reference, in which case the elements // inside the tuple may be modified. // // Example: // // struct Stringify { // template // void operator()(T& t, std::vector& out) const { // out.push_back(std::to_string(t)); // } // }; // auto tup = std::make_tuple(true, 42); // std::vector v; // internal::ForEach(tup, Stringify{}, v); // EXPECT_THAT(v, testing::ElementsAre("1", "42")); // template typename std::enable_if<(I < TupleSize::value), void>::type ForEach( T&& t, F&& f, Args&&... args) { auto&& e = std::get(std::forward(t)); std::forward(f)(std::forward(e), std::forward(args)...); ForEach(std::forward(t), std::forward(f), std::forward(args)...); } } // namespace internal } // namespace SPANNER_CLIENT_NS } // namespace spanner } // namespace cloud } // namespace google #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_INTERNAL_TUPLE_UTILS_H