Explorar o código

feat: add binding for deferred default values

Sam Jaffe %!s(int64=3) %!d(string=hai) anos
pai
achega
fe2d3903e7

+ 8 - 1
include/program_args/arguments.h

@@ -127,7 +127,13 @@ template <typename B, typename V>
 struct Arguments<Impl>::WithDefault {
   B impl;
   V default_value;
-  template <typename T> operator T() const { return impl ?: T(default_value); }
+  template <typename T> operator T() const {
+    if constexpr (std::is_convertible<V, T>{}) {
+      return impl ?: T(default_value);
+    } else {
+      return impl ?: T(default_value());
+    }
+  }
 };
 
 }
@@ -148,3 +154,4 @@ int typed_main(Args const &, Action const &);
   }                                                                            \
   int typed_main(tname const & args)
 
+#define PROGRAM_DEFER(...) [this]() { return __VA_ARGS__; }

+ 4 - 0
include/program_args/arguments_impl.hpp

@@ -41,6 +41,10 @@ template <typename Impl> bool Arguments<Impl>::Action::primed() const {
   return false;
 }
 
+}
+
+namespace program {
+
 template <typename Impl>
 template <typename T>
 Arguments<Impl>::Argument::operator T() const {

+ 24 - 0
test/options_test.cpp

@@ -7,6 +7,8 @@
 
 #include "program_args/arguments.h"
 
+#include <filesystem>
+
 #include "xcode_gtest_helper.h"
 
 using testing::ElementsAre;
@@ -164,3 +166,25 @@ TEST(LongOptionRepeatWithDefaultTest, ArgumentOverwritesDefault) {
       parse<LongOptionRepeatWithDefaultTest>({"", "--port", "443"});
   EXPECT_THAT(options.port, ElementsAre(443));
 }
+
+namespace fs = std::filesystem;
+struct DeferOptionTest : program::Arguments<DeferOptionTest> {
+  using Arguments::Arguments;
+  fs::path path = option("path") = ".";
+  fs::path log = option("log") = PROGRAM_DEFER(path / "test.log");
+};
+
+TEST(DeferOptionTest, DefaultResolves) {
+  auto const options = parse<DeferOptionTest>({""});
+  EXPECT_THAT(options.log.string(), "./test.log");
+}
+
+TEST(DeferOptionTest, CapturesUpdateToDependent) {
+  auto const options = parse<DeferOptionTest>({"", "--path", "/var/log"});
+  EXPECT_THAT(options.log.string(), "/var/log/test.log");
+}
+
+TEST(DeferOptionTest, SettingActualArgWillOverwrite) {
+  auto const options = parse<DeferOptionTest>({"", "--path", "/var/log", "--log", "test.log"});
+  EXPECT_THAT(options.log.string(), "test.log");
+}