Coverage Report

Created: 2026-08-14 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/abseil-cpp/absl/flags/commandlineflag.h
Line
Count
Source
1
//
2
// Copyright 2020 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
// -----------------------------------------------------------------------------
17
// File: commandlineflag.h
18
// -----------------------------------------------------------------------------
19
//
20
// This header file defines the `CommandLineFlag`, which acts as a type-erased
21
// handle for accessing metadata about the Abseil Flag in question.
22
//
23
// Because an actual Abseil flag is of an unspecified type, you should not
24
// manipulate or interact directly with objects of that type. Instead, use the
25
// CommandLineFlag type as an intermediary.
26
#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
27
#define ABSL_FLAGS_COMMANDLINEFLAG_H_
28
29
#include <memory>
30
#include <optional>
31
#include <string>
32
33
#include "absl/base/config.h"
34
#include "absl/base/fast_type_id.h"
35
#include "absl/base/nullability.h"
36
#include "absl/flags/internal/commandlineflag.h"
37
#include "absl/strings/string_view.h"
38
#include "absl/types/optional.h"
39
40
namespace absl {
41
ABSL_NAMESPACE_BEGIN
42
namespace flags_internal {
43
class PrivateHandleAccessor;
44
}  // namespace flags_internal
45
46
// CommandLineFlag
47
//
48
// This type acts as a type-erased handle for an instance of an Abseil Flag and
49
// holds reflection information pertaining to that flag. Use CommandLineFlag to
50
// access a flag's name, location, help string etc.
51
//
52
// To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`
53
// passing it the flag name string.
54
//
55
// Example:
56
//
57
//   // Obtain reflection handle for a flag named "flagname".
58
//   const absl::CommandLineFlag* my_flag_data =
59
//        absl::FindCommandLineFlag("flagname");
60
//
61
//   // Now you can get flag info from that reflection handle.
62
//   std::string flag_location = my_flag_data->Filename();
63
//   ...
64
65
// These are only used as constexpr global objects.
66
// They do not use a virtual destructor to simplify their implementation.
67
// They are not destroyed except at program exit, so leaks do not matter.
68
#if defined(__GNUC__) && !defined(__clang__)
69
#pragma GCC diagnostic push
70
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
71
#endif
72
class CommandLineFlag {
73
 public:
74
0
  constexpr CommandLineFlag() = default;
75
76
  // Not copyable/assignable.
77
  CommandLineFlag(const CommandLineFlag&) = delete;
78
  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
79
80
  // absl::CommandLineFlag::IsOfType()
81
  //
82
  // Return true iff flag has type T.
83
  template <typename T>
84
  inline bool IsOfType() const {
85
    return TypeId() == FastTypeId<T>();
86
  }
87
88
  // absl::CommandLineFlag::TryGet()
89
  //
90
  // Attempts to retrieve the flag value. Returns value on success,
91
  // std::nullopt otherwise.
92
  template <typename T>
93
  std::optional<T> TryGet() const {
94
    if (IsRetired() || !IsOfType<T>()) {
95
      return std::nullopt;
96
    }
97
98
    // Implementation notes:
99
    //
100
    // We are wrapping a union around the value of `T` to serve three purposes:
101
    //
102
    //  1. `U.value` has correct size and alignment for a value of type `T`
103
    //  2. The `U.value` constructor is not invoked since U's constructor does
104
    //     not do it explicitly.
105
    //  3. The `U.value` destructor is invoked since U's destructor does it
106
    //     explicitly. This makes `U` a kind of RAII wrapper around non default
107
    //     constructible value of T, which is destructed when we leave the
108
    //     scope. We do need to destroy U.value, which is constructed by
109
    //     CommandLineFlag::Read even though we left it in a moved-from state
110
    //     after std::move.
111
    //
112
    // All of this serves to avoid requiring `T` being default constructible.
113
    union U {
114
      T value;
115
      U() {}
116
      ~U() { value.~T(); }
117
    };
118
    U u;
119
120
    Read(&u.value);
121
    // allow retired flags to be "read", so we can report invalid access.
122
    if (IsRetired()) {
123
      return std::nullopt;
124
    }
125
    return std::move(u.value);
126
  }
127
128
  // absl::CommandLineFlag::Name()
129
  //
130
  // Returns name of this flag.
131
  virtual absl::string_view Name() const = 0;
132
133
  // absl::CommandLineFlag::Filename()
134
  //
135
  // Returns name of the file where this flag is defined.
136
  virtual std::string Filename() const = 0;
137
138
  // absl::CommandLineFlag::Help()
139
  //
140
  // Returns help message associated with this flag.
141
  virtual std::string Help() const = 0;
142
143
  // absl::CommandLineFlag::IsRetired()
144
  //
145
  // Returns true iff this object corresponds to retired flag.
146
  virtual bool IsRetired() const;
147
148
  // absl::CommandLineFlag::DefaultValue()
149
  //
150
  // Returns the default value for this flag.
151
  virtual std::string DefaultValue() const = 0;
152
153
  // absl::CommandLineFlag::CurrentValue()
154
  //
155
  // Returns the current value for this flag.
156
  virtual std::string CurrentValue() const = 0;
157
158
  // absl::CommandLineFlag::ParseFrom()
159
  //
160
  // Sets the value of the flag based on specified string `value`. If the flag
161
  // was successfully set to new value, it returns true. Otherwise, sets `error`
162
  // to indicate the error, leaves the flag unchanged, and returns false.
163
  bool ParseFrom(absl::string_view value, std::string* absl_nonnull error);
164
165
 protected:
166
  ~CommandLineFlag() = default;
167
168
 private:
169
  friend class flags_internal::PrivateHandleAccessor;
170
171
  // Sets the value of the flag based on specified string `value`. If the flag
172
  // was successfully set to new value, it returns true. Otherwise, sets `error`
173
  // to indicate the error, leaves the flag unchanged, and returns false. There
174
  // are three ways to set the flag's value:
175
  //  * Update the current flag value
176
  //  * Update the flag's default value
177
  //  * Update the current flag value if it was never set before
178
  // The mode is selected based on `set_mode` parameter.
179
  virtual bool ParseFrom(absl::string_view value,
180
                         flags_internal::FlagSettingMode set_mode,
181
                         flags_internal::ValueSource source,
182
                         std::string& error) = 0;
183
184
  // Returns id of the flag's value type.
185
  virtual flags_internal::FlagFastTypeId TypeId() const = 0;
186
187
  // Interface to save flag to some persistent state. Returns current flag state
188
  // or nullptr if flag does not support saving and restoring a state.
189
  virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
190
191
  // Copy-construct a new value of the flag's type in a memory referenced by
192
  // the dst based on the current flag's value.
193
  virtual void Read(void* absl_nonnull dst) const = 0;
194
195
  // To be deleted. Used to return true if flag's current value originated from
196
  // command line.
197
  virtual bool IsSpecifiedOnCommandLine() const = 0;
198
199
  // Validates supplied value using validator or parseflag routine
200
  virtual bool ValidateInputValue(absl::string_view value) const = 0;
201
202
  // Checks that flags default value can be converted to string and back to the
203
  // flag's value type.
204
  virtual void CheckDefaultValueParsingRoundtrip() const = 0;
205
206
  // absl::CommandLineFlag::TypeName()
207
  //
208
  // Returns string representation of the type of this flag
209
  // (the way it is spelled in the ABSL_FLAG macro).
210
  // The default implementation returns the empty string.
211
  virtual absl::string_view TypeName() const;
212
};
213
#if defined(__GNUC__) && !defined(__clang__)
214
#pragma GCC diagnostic pop
215
#endif
216
217
ABSL_NAMESPACE_END
218
}  // namespace absl
219
220
#endif  // ABSL_FLAGS_COMMANDLINEFLAG_H_