// Copyright 2021 gRPC authors. // // 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 GRPC_SRC_CORE_LIB_GPRPP_TABLE_H #define GRPC_SRC_CORE_LIB_GPRPP_TABLE_H #include <grpc/support/port_platform.h> #include <stddef.h> #include <initializer_list> #include <new> #include <type_traits> #include <utility> #include "absl/meta/type_traits.h" #include "absl/utility/utility.h" #include "src/core/lib/gprpp/bitset.h" namespace grpc_core { // Meta-programming detail types to aid in building up a Table namespace table_detail { // A tuple-like type that contains manually constructed elements. template <typename... Ts> struct Elements; Elements<T, Ts...>; template <> struct Elements<> { … }; // Element accessor for Elements<> // Provides a static method f that returns a pointer to the value of element I // for Elements<Ts...> template <size_t I, typename... Ts> struct GetElem; GetElem<0, T, Ts...>; GetElem<I, T, Ts...>; // CountIncludedStruct is the backing for the CountIncluded function below. // Sets a member constant N to the number of times Needle is in Haystack. template <typename Needle, typename... Haystack> struct CountIncludedStruct; CountIncludedStruct<Needle, Straw, RestOfHaystack...>; CountIncludedStruct<Needle>; // Returns the number of times Needle is in Haystack. template <typename Needle, typename... Haystack> constexpr size_t CountIncluded() { … } // IndexOfStruct is the backing for IndexOf below. // Set a member constant N to the index of Needle in Haystack. // Ignored should be void always, and is used for enable_if_t. template <typename Ignored, typename Needle, typename... Haystack> struct IndexOfStruct; IndexOfStruct<absl::enable_if_t<std::is_same<Needle, Straw>::value>, Needle, Straw, RestOfHaystack...>; IndexOfStruct<absl::enable_if_t<!std::is_same<Needle, Straw>::value>, Needle, Straw, RestOfHaystack...>; // Return the index of Needle in Haystack. // Guarded by CountIncluded to ensure that the return type is unambiguous. // If you got here from a compiler error using Table, it's likely that you've // used the type-based accessor/mutators, but the type you're using is repeated // more than once in the Table type arguments. Consider either using the indexed // accessor/mutator variants, or eliminating the ambiguity in type resolution. template <typename Needle, typename... Haystack> constexpr absl::enable_if_t<CountIncluded<Needle, Haystack...>() == 1, size_t> IndexOf() { … } // TypeIndexStruct is the backing for TypeIndex below. // Sets member type Type to the type at index I in Ts. // Implemented as a simple type recursion. template <size_t I, typename... Ts> struct TypeIndexStruct; TypeIndexStruct<0, T, Ts...>; TypeIndexStruct<I, T, Ts...>; // TypeIndex is the type at index I in Ts. TypeIndex; // Helper to call the destructor of p if p is non-null. template <typename T> void DestructIfNotNull(T* p) { … } // Helper function... just ignore the initializer list passed into it. // Allows doing 'statements' via parameter pack expansion in C++11 - given // template <typename... Ts>: // do_these_things({(foo<Ts>(), 1)}); // will execute foo<T>() for each T in Ts. // In this example we also leverage the comma operator to make the resultant // type of each statement be a consistant int so that C++ type deduction works // as we'd like (note that in the expression (a, 1) in C++, the 'result' of the // expression is the value after the right-most ',' -- in this case 1, with a // executed as a side effect. template <typename T> void do_these_things(std::initializer_list<T>) { … } } // namespace table_detail // A Table<Ts> is much like a tuple<optional<Ts>...> - a set of values that are // optionally present. Table efficiently packs the presence bits for size, and // provides a slightly more convenient interface. template <typename... Ts> class Table { … }; } // namespace grpc_core #endif // GRPC_SRC_CORE_LIB_GPRPP_TABLE_H