about summary refs log tree commit diff
path: root/absl/flags
diff options
context:
space:
mode:
Diffstat (limited to 'absl/flags')
-rw-r--r--absl/flags/flag.h12
-rw-r--r--absl/flags/flag_test.cc23
-rw-r--r--absl/flags/internal/flag.h14
3 files changed, 47 insertions, 2 deletions
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index b6fbd116ed2f..f18e9f56a5cc 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -384,11 +384,19 @@ ABSL_NAMESPACE_END
 //
 // `default_value` is only used as a double check on the type. `explanation` is
 // unused.
+//
+// ABSL_RETIRED_FLAG support omitting the default value for default
+// constructible value type, so that users can delete the code generatring this
+// value.
+//
 // TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
 // the unnamed namespace.
 #define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \
-  ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =        \
-      ([] { return type(default_value); },                            \
+  ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =             \
+      ([] {                                                                \
+           return absl::flags_internal::MakeFromDefaultValueOrEmpty<type>( \
+                   default_value);                                         \
+       },                                                                  \
        absl::flags_internal::RetiredFlag<type>(#flagname))
 
 #endif  // ABSL_FLAGS_FLAG_H_
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index 4e08da8589a5..465f018c5e4f 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -486,11 +486,30 @@ TEST_F(FlagTest, TestNonDefaultConstructibleType) {
 
 // --------------------------------------------------------------------
 
+struct Wrapper {
+  Wrapper() {}
+
+  // NOLINTNEXTLINE(runtime/explicit)
+  Wrapper(const std::string& val) : val(val) {}
+
+  // NOLINTNEXTLINE(runtime/explicit)
+  template <typename T>
+  Wrapper(T&& t) : val(std::forward<T>(t)) {}
+
+  // NOLINTNEXTLINE(runtime/explicit)
+  operator std::string() const& { return val; }
+
+  std::string val;
+};
+
 }  // namespace
 
 ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
 ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
 ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
+ABSL_RETIRED_FLAG(Wrapper, old_wrapper_flag, {}, "old wrapper");
+ABSL_RETIRED_FLAG(Wrapper, old_wrapper_no_default_flag, ,
+                  "old wrapper no default");
 
 namespace {
 
@@ -502,6 +521,10 @@ TEST_F(FlagTest, TestRetiredFlagRegistration) {
   EXPECT_FALSE(is_bool);
   EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));
   EXPECT_FALSE(is_bool);
+  EXPECT_TRUE(flags::IsRetiredFlag("old_wrapper_flag", &is_bool));
+  EXPECT_FALSE(is_bool);
+  EXPECT_TRUE(flags::IsRetiredFlag("old_wrapper_no_default_flag", &is_bool));
+  EXPECT_FALSE(is_bool);
   EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));
 }
 
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 20de406f4615..21a10c7f85f8 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -416,6 +416,20 @@ T* MakeFromDefaultValue(EmptyBraces) {
   return new T;
 }
 
+// MakeFromDefaultValueOrEmpty is basically the same as MakeFromDefaultValue. It
+// also allows for empty macro parameter (hence no argument), which was somehow
+// widely used for ABSL_RETIRED_FLAG().
+
+template <typename T>
+T* MakeFromDefaultValueOrEmpty(T t) {
+  return MakeFromDefaultValue(std::move(t));
+}
+
+template <typename T>
+T* MakeFromDefaultValueOrEmpty() {
+  return MakeFromDefaultValue<T>(EmptyBraces());
+}
+
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl