about summary refs log tree commit diff
path: root/absl/flags/internal/flag.h
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
committerVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
commit8f2828c4b4ce502d242eca80a80269448857f4a6 (patch)
treecc3fad62dff6f279ce77f17047c4eef5ebbaf251 /absl/flags/internal/flag.h
parent768eb2ca2857342673fcd462792ce04b8bac3fa3 (diff)
Squashed 'third_party/abseil_cpp/' changes from 768eb2ca2..ccdbb5941
ccdbb5941 Export of internal Abseil changes
01f5f81f9 Export of internal Abseil changes
2c92bdc7c Export of internal Abseil changes
e7ebf9803 Export of internal Abseil changes
2eba343b5 Export of internal Abseil changes
a8b03d90e Export of internal Abseil changes
1d31b5c36 Export of internal Abseil changes
da3a87690 Export of internal Abseil changes
8faf20461 Exclude empty directories (#697)
2069dc796 Export of internal Abseil changes
4832bf6bf Added a BUILD file in root to expose license. (#695)
af8f994af Export of internal Abseil changes
33caf1097 Export of internal Abseil changes
cf1a02e2d Export of internal Abseil changes

git-subtree-dir: third_party/abseil_cpp
git-subtree-split: ccdbb5941f992fabda7eae3ce72f55efc17c826a
Diffstat (limited to 'absl/flags/internal/flag.h')
-rw-r--r--absl/flags/internal/flag.h105
1 files changed, 65 insertions, 40 deletions
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index e374ecde3d..2cc44e00f7 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -16,31 +16,36 @@
 #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
 #define ABSL_FLAGS_INTERNAL_FLAG_H_
 
+#include <stddef.h>
 #include <stdint.h>
 
 #include <atomic>
 #include <cstring>
 #include <memory>
+#include <new>
 #include <string>
 #include <type_traits>
 #include <typeinfo>
 
+#include "absl/base/attributes.h"
 #include "absl/base/call_once.h"
 #include "absl/base/config.h"
+#include "absl/base/optimization.h"
 #include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/config.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/registry.h"
 #include "absl/flags/marshalling.h"
-#include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
-#include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
+///////////////////////////////////////////////////////////////////////////////
 // Forward declaration of absl::Flag<T> public API.
 namespace flags_internal {
 template <typename T>
@@ -64,12 +69,15 @@ void SetFlag(absl::Flag<T>* flag, const T& v);
 template <typename T, typename V>
 void SetFlag(absl::Flag<T>* flag, const V& v);
 
-namespace flags_internal {
+template <typename U>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
 
 ///////////////////////////////////////////////////////////////////////////////
 // Flag value type operations, eg., parsing, copying, etc. are provided
 // by function specific to that type with a signature matching FlagOpFn.
 
+namespace flags_internal {
+
 enum class FlagOp {
   kAlloc,
   kDelete,
@@ -168,6 +176,28 @@ inline const std::type_info* GenRuntimeTypeId() {
 // cases.
 using HelpGenFunc = std::string (*)();
 
+template <size_t N>
+struct FixedCharArray {
+  char value[N];
+
+  template <size_t... I>
+  static constexpr FixedCharArray<N> FromLiteralString(
+      absl::string_view str, absl::index_sequence<I...>) {
+    return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
+  }
+};
+
+template <typename Gen, size_t N = Gen::Value().size()>
+constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
+  return FixedCharArray<N + 1>::FromLiteralString(
+      Gen::Value(), absl::make_index_sequence<N>{});
+}
+
+template <typename Gen>
+constexpr std::false_type HelpStringAsArray(char) {
+  return std::false_type{};
+}
+
 union FlagHelpMsg {
   constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
   constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
@@ -185,40 +215,28 @@ struct FlagHelpArg {
 
 extern const char kStrippedFlagHelp[];
 
-// HelpConstexprWrap is used by struct AbslFlagHelpGenFor##name generated by
-// ABSL_FLAG macro. It is only used to silence the compiler in the case where
-// help message expression is not constexpr and does not have type const char*.
-// If help message expression is indeed constexpr const char* HelpConstexprWrap
-// is just a trivial identity function.
-template <typename T>
-const char* HelpConstexprWrap(const T&) {
-  return nullptr;
-}
-constexpr const char* HelpConstexprWrap(const char* p) { return p; }
-constexpr const char* HelpConstexprWrap(char* p) { return p; }
-
 // These two HelpArg overloads allows us to select at compile time one of two
 // way to pass Help argument to absl::Flag. We'll be passing
-// AbslFlagHelpGenFor##name as T and integer 0 as a single argument to prefer
-// first overload if possible. If T::Const is evaluatable on constexpr
-// context (see non template int parameter below) we'll choose first overload.
-// In this case the help message expression is immediately evaluated and is used
-// to construct the absl::Flag. No additionl code is generated by ABSL_FLAG.
-// Otherwise SFINAE kicks in and first overload is dropped from the
+// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
+// first overload if possible. If help message is evaluatable on constexpr
+// context We'll be able to make FixedCharArray out of it and we'll choose first
+// overload. In this case the help message expression is immediately evaluated
+// and is used to construct the absl::Flag. No additionl code is generated by
+// ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the
 // consideration, in which case the second overload will be used. The second
 // overload does not attempt to evaluate the help message expression
 // immediately and instead delays the evaluation by returing the function
 // pointer (&T::NonConst) genering the help message when necessary. This is
 // evaluatable in constexpr context, but the cost is an extra function being
 // generated in the ABSL_FLAG code.
-template <typename T, int = (T::Const(), 1)>
-constexpr FlagHelpArg HelpArg(int) {
-  return {FlagHelpMsg(T::Const()), FlagHelpKind::kLiteral};
+template <typename Gen, size_t N>
+constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
+  return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
 }
 
-template <typename T>
-constexpr FlagHelpArg HelpArg(char) {
-  return {FlagHelpMsg(&T::NonConst), FlagHelpKind::kGenFunc};
+template <typename Gen>
+constexpr FlagHelpArg HelpArg(std::false_type) {
+  return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -364,31 +382,31 @@ struct FlagValue;
 
 template <typename T>
 struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
-  bool Get(T*) const { return false; }
+  bool Get(T&) const { return false; }
 
   alignas(T) char value[sizeof(T)];
 };
 
 template <typename T>
 struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
-  bool Get(T* dst) const {
+  bool Get(T& dst) const {
     int64_t one_word_val = value.load(std::memory_order_acquire);
     if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) {
       return false;
     }
-    std::memcpy(dst, static_cast<const void*>(&one_word_val), sizeof(T));
+    std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
     return true;
   }
 };
 
 template <typename T>
 struct FlagValue<T, FlagValueStorageKind::kTwoWordsAtomic> : FlagTwoWordsValue {
-  bool Get(T* dst) const {
+  bool Get(T& dst) const {
     AlignedTwoWords two_words_val = value.load(std::memory_order_acquire);
     if (ABSL_PREDICT_FALSE(!two_words_val.IsInitialized())) {
       return false;
     }
-    std::memcpy(dst, static_cast<const void*>(&two_words_val), sizeof(T));
+    std::memcpy(&dst, static_cast<const void*>(&two_words_val), sizeof(T));
     return true;
   }
 };
@@ -419,7 +437,7 @@ struct DynValueDeleter {
 
 class FlagState;
 
-class FlagImpl final : public flags_internal::CommandLineFlag {
+class FlagImpl final : public CommandLineFlag {
  public:
   constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
                      FlagHelpArg help, FlagValueStorageKind value_kind,
@@ -492,7 +510,7 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
   // Attempts to parse supplied `value` string. If parsing is successful,
   // returns new value. Otherwise returns nullptr.
   std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
-                                                  std::string* err) const
+                                                  std::string& err) const
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
   // Stores the flag value based on the pointer to the source.
   void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
@@ -534,7 +552,7 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
       ABSL_LOCKS_EXCLUDED(*DataGuard());
 
   bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
-                 ValueSource source, std::string* error) override
+                 ValueSource source, std::string& error) override
       ABSL_LOCKS_EXCLUDED(*DataGuard());
 
   // Immutable flag's state.
@@ -641,7 +659,7 @@ class Flag {
     impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
 #endif
 
-    if (!value_.Get(&u.value)) impl_.Read(&u.value);
+    if (!value_.Get(u.value)) impl_.Read(&u.value);
     return std::move(u.value);
   }
   void Set(const T& v) {
@@ -649,6 +667,13 @@ class Flag {
     impl_.Write(&v);
   }
 
+  template <typename U>
+  friend const CommandLineFlag& absl::GetFlagReflectionHandle(
+      const absl::Flag<U>& f);
+
+  // Access to the reflection.
+  const CommandLineFlag& Reflect() const { return impl_; }
+
   // Flag's data
   // The implementation depends on value_ field to be placed exactly after the
   // impl_ field, so that impl_ can figure out the offset to the value and
@@ -720,12 +745,12 @@ struct FlagRegistrarEmpty {};
 template <typename T, bool do_register>
 class FlagRegistrar {
  public:
-  explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
-    if (do_register) flags_internal::RegisterCommandLineFlag(&flag_->impl_);
+  explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) {
+    if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_);
   }
 
   FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
-    flag_->impl_.SetCallback(cb);
+    flag_.impl_.SetCallback(cb);
     return *this;
   }
 
@@ -735,7 +760,7 @@ class FlagRegistrar {
   operator FlagRegistrarEmpty() const { return {}; }  // NOLINT
 
  private:
-  Flag<T>* flag_;  // Flag being registered (not owned).
+  Flag<T>& flag_;  // Flag being registered (not owned).
 };
 
 }  // namespace flags_internal