15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_OPTIONS_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_OPTIONS_H
18 #include "google/cloud/internal/type_list.h"
19 #include "google/cloud/version.h"
20 #include "absl/base/attributes.h"
21 #include "absl/memory/memory.h"
25 #include <unordered_map>
34 void CheckExpectedOptionsImpl(std::set<std::type_index>
const&,
Options const&,
37 inline T
const& DefaultValue() {
38 static auto const*
const kDefaultValue =
new T{};
39 return *kDefaultValue;
90 using ValueTypeT =
typename T::Type;
97 for (
auto const& kv : rhs.m_) m_.emplace(kv.first, kv.second->clone());
101 std::swap(m_, tmp.m_);
120 template <
typename T>
122 m_[
typeid(T)] = absl::make_unique<Data<T>>(std::move(v));
131 template <
typename T>
133 return m_.find(
typeid(T)) != m_.end();
141 template <
typename T>
169 template <
typename T>
170 ValueTypeT<T>
const&
get()
const {
171 auto const it = m_.find(
typeid(T));
172 if (it == m_.end())
return internal::DefaultValue<ValueTypeT<T>>();
173 auto const* value = it->second->data_address();
174 return *
reinterpret_cast<ValueTypeT<T>
const*>(value);
197 template <
typename T>
198 ValueTypeT<T>&
lookup(ValueTypeT<T> value = {}) {
199 auto p = m_.find(
typeid(T));
201 p = m_.emplace(
typeid(T), absl::make_unique<Data<T>>(std::move(value)))
204 auto* v = p->second->data_address();
205 return *
reinterpret_cast<ValueTypeT<T>*>(v);
210 friend void internal::CheckExpectedOptionsImpl(
211 std::set<std::type_index>
const&,
Options const&,
char const*);
216 virtual ~DataHolder() =
default;
217 virtual void const* data_address()
const = 0;
218 virtual void* data_address() = 0;
219 virtual std::unique_ptr<DataHolder> clone()
const = 0;
223 template <
typename T>
224 class Data :
public DataHolder {
226 explicit Data(ValueTypeT<T> v) : value_(std::move(v)) {}
227 ~Data()
override =
default;
229 void const* data_address()
const override {
return &value_; }
230 void* data_address()
override {
return &value_; }
231 std::unique_ptr<DataHolder> clone()
const override {
232 return absl::make_unique<Data<T>>(*
this);
236 ValueTypeT<T> value_;
242 std::unordered_map<std::type_index, std::unique_ptr<DataHolder>> m_;
253 template <
typename... T>
254 using OptionList = internal::TypeList<T...>;
259 template <
typename T>
260 struct WrapTypeList {
261 using Type = OptionList<T>;
263 template <
typename... T>
264 struct WrapTypeList<OptionList<T...>> {
265 using Type = OptionList<T...>;
267 template <
typename T>
268 using WrapTypeListT =
typename WrapTypeList<T>::Type;
270 template <
typename... T>
271 void CheckExpectedOptionsImpl(OptionList<T...>
const&,
Options const& opts,
272 char const* caller) {
273 CheckExpectedOptionsImpl({
typeid(T)...}, opts, caller);
305 template <
typename... T>
306 void CheckExpectedOptions(
Options const& opts,
char const* caller) {
307 using ExpectedTypes = TypeListCatT<WrapTypeListT<T>...>;
308 CheckExpectedOptionsImpl(ExpectedTypes{}, opts, caller);
321 Options const& CurrentOptions();
343 class ABSL_MUST_USE_RESULT OptionsSpan {
345 explicit OptionsSpan(
Options opts);
348 OptionsSpan(OptionsSpan
const&) =
delete;
349 OptionsSpan(OptionsSpan&&) =
delete;
350 OptionsSpan& operator=(OptionsSpan
const&) =
delete;
351 OptionsSpan& operator=(OptionsSpan&&) =
delete;
354 static void* operator
new(std::size_t) =
delete;
355 static void* operator
new[](std::size_t) =
delete;