1//
2// Copyright 2019 The Abseil Authors.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// https://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
17#define ABSL_FLAGS_INTERNAL_FLAG_H_
18
19#include "absl/flags/internal/commandlineflag.h"
20#include "absl/flags/internal/registry.h"
21
22namespace absl {
23namespace flags_internal {
24
25// This is "unspecified" implementation of absl::Flag<T> type.
26template <typename T>
27class Flag {
28 public:
29 constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
30 const char* filename,
31 const flags_internal::FlagMarshallingOpFn marshalling_op,
32 const flags_internal::InitialValGenFunc initial_value_gen)
33 : internal(name, flags_internal::HelpText::FromFunctionPointer(help_gen),
34 filename, &flags_internal::FlagOps<T>, marshalling_op,
35 initial_value_gen,
36 /*retired_arg=*/false, /*def_arg=*/nullptr,
37 /*cur_arg=*/nullptr) {}
38
39 // Not copyable/assignable.
40 Flag(const Flag<T>&) = delete;
41 Flag<T>& operator=(const Flag<T>&) = delete;
42
43 absl::string_view Name() const { return internal.Name(); }
44 std::string Help() const { return internal.Help(); }
45 std::string Filename() const { return internal.Filename(); }
46
47 absl::flags_internal::CommandLineFlag internal;
48
49 void SetCallback(const flags_internal::FlagCallback mutation_callback) {
50 internal.SetCallback(mutation_callback);
51 }
52
53 private:
54 // TODO(rogeeff): add these validations once UnparseFlag invocation is fixed
55 // for built-in types and when we cleanup existing code from operating on
56 // forward declared types.
57 // auto IsCopyConstructible(const T& v) -> decltype(T(v));
58 // auto HasAbslParseFlag(absl::string_view in, T* dst, std::string* err)
59 // -> decltype(AbslParseFlag(in, dst, err));
60 // auto HasAbslUnparseFlag(const T& v) -> decltype(AbslUnparseFlag(v));
61};
62
63// This class facilitates Flag object registration and tail expression-based
64// flag definition, for example:
65// ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
66template <typename T, bool do_register>
67class FlagRegistrar {
68 public:
69 explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
70 if (do_register) flags_internal::RegisterCommandLineFlag(&flag_->internal);
71 }
72
73 FlagRegistrar& OnUpdate(flags_internal::FlagCallback cb) && {
74 flag_->SetCallback(cb);
75 return *this;
76 }
77
78 // Make the registrar "die" gracefully as a bool on a line where registration
79 // happens. Registrar objects are intended to live only as temporary.
80 operator bool() const { return true; } // NOLINT
81
82 private:
83 Flag<T>* flag_; // Flag being registered (not owned).
84};
85
86// This struct and corresponding overload to MakeDefaultValue are used to
87// facilitate usage of {} as default value in ABSL_FLAG macro.
88struct EmptyBraces {};
89
90template <typename T>
91T* MakeFromDefaultValue(T t) {
92 return new T(std::move(t));
93}
94
95template <typename T>
96T* MakeFromDefaultValue(EmptyBraces) {
97 return new T;
98}
99
100} // namespace flags_internal
101} // namespace absl
102
103#endif // ABSL_FLAGS_INTERNAL_FLAG_H_
104