chromium/third_party/grpc/src/src/core/lib/gprpp/table.h

// 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