diff --git a/include/argparse.hpp b/include/argparse.hpp index 94c5f1d..71c7a35 100644 --- a/include/argparse.hpp +++ b/include/argparse.hpp @@ -103,12 +103,17 @@ namespace argparse class Converter { public: - auto from_string(std::string const & s, T & t) const -> bool + auto from_string(std::string const & s) const -> std::optional { auto iss = std::istringstream(s); + auto t = T(); iss >> t; - return !iss.fail() && (iss.eof() || iss.peek() == std::istringstream::traits_type::eof()); + if (!iss.fail() && (iss.eof() || iss.peek() == std::istringstream::traits_type::eof())) + { + return t; + } + return std::nullopt; } auto to_string(T const & t) const -> std::string @@ -126,10 +131,10 @@ namespace argparse }; template - inline auto from_string(std::string const & s, T & t) -> bool + inline auto from_string(std::string const & s) -> std::optional { auto const conv = Converter(); - return conv.from_string(s, t); + return conv.from_string(s); } template @@ -546,10 +551,9 @@ namespace argparse } else { - auto value = T(); - if (argparse::from_string(string, value)) + if (auto const optvalue = argparse::from_string(string); optvalue.has_value()) { - return std::any(value); + return std::any(*optvalue); } else { @@ -990,7 +994,7 @@ namespace argparse static auto is_negative_number(std::string const & token) -> bool { - if (auto num = double(); from_string(token, num)) + if (auto const parsed = from_string(token); parsed.has_value()) { return true; } diff --git a/test/unittest/custom.h b/test/unittest/custom.h index 1218888..949ac6c 100644 --- a/test/unittest/custom.h +++ b/test/unittest/custom.h @@ -27,10 +27,10 @@ template<> class Converter { public: - auto from_string(std::string const & s, foo::Custom & t) const -> bool + auto from_string(std::string const & s) const -> std::optional { - t = foo::Custom(s); - return true; + auto t = foo::Custom(s); + return t; } auto to_string(foo::Custom const & t) const -> std::string diff --git a/tutorial/custom1.cpp b/tutorial/custom1.cpp index 3ce1101..6a725f5 100644 --- a/tutorial/custom1.cpp +++ b/tutorial/custom1.cpp @@ -24,12 +24,13 @@ template<> class Converter { public: - auto from_string(std::string const & s, geometry::Point & p) const -> bool + auto from_string(std::string const & s) const -> std::optional { std::istringstream iss(s); + auto p = geometry::Point(); char comma; iss >> p.x >> comma >> p.y; - return true; + return p; } auto to_string(geometry::Point const & p) const -> std::string diff --git a/tutorial/custom2.cpp b/tutorial/custom2.cpp index 4c1e7c5..b497438 100644 --- a/tutorial/custom2.cpp +++ b/tutorial/custom2.cpp @@ -24,12 +24,15 @@ template<> class Converter { public: - auto from_string(std::string const & s, geometry::Point & p) const -> bool + auto from_string(std::string const & s) const -> std::optional { std::istringstream iss(s); + auto p = geometry::Point(); char comma; iss >> p.x >> comma >> p.y; - return !iss.fail(); + return !iss.fail() + ? std::optional(p) + : std::nullopt; } auto to_string(geometry::Point const & p) const -> std::string diff --git a/tutorial/custom3.cpp b/tutorial/custom3.cpp index 7b98e1d..a01aa2e 100644 --- a/tutorial/custom3.cpp +++ b/tutorial/custom3.cpp @@ -24,12 +24,15 @@ template<> class Converter { public: - auto from_string(std::string const & s, geometry::Point & p) const -> bool + auto from_string(std::string const & s) const -> std::optional { std::istringstream iss(s); + auto p = geometry::Point(); char comma; iss >> p.x >> comma >> p.y; - return !iss.fail(); + return !iss.fail() + ? std::optional(p) + : std::nullopt; } auto to_string(geometry::Point const & p) const -> std::string diff --git a/tutorial/readme.md b/tutorial/readme.md index 49bc635..a7f08da 100644 --- a/tutorial/readme.md +++ b/tutorial/readme.md @@ -958,12 +958,13 @@ template<> class Converter { public: - auto from_string(std::string const & s, geometry::Point & p) const -> bool + auto from_string(std::string const & s) const -> std::optional { std::istringstream iss(s); + auto p = geometry::Point(); char comma; iss >> p.x >> comma >> p.y; - return true; + return p; } auto to_string(geometry::Point const & p) const -> std::string @@ -1005,7 +1006,7 @@ optional arguments: $ custom1 0,0 1,1 The distance is 1.41421 ``` -The return value of `argparse::Converter::from_string` indicates whether the conversion succeeded. You can use it to your advantage (`custom2.cpp`): +The `argparse::Converter::from_string` function should return an empty optional to indicate conversion failure. You can use it to your advantage (`custom2.cpp`): ```c++ #include "argparse.hpp" #include @@ -1033,12 +1034,15 @@ template<> class Converter { public: - auto from_string(std::string const & s, geometry::Point & p) const -> bool + auto from_string(std::string const & s) const -> std::optional { std::istringstream iss(s); + auto p = geometry::Point(); char comma; iss >> p.x >> comma >> p.y; - return !iss.fail(); + return !iss.fail() + ? std::optional(p) + : std::nullopt; } auto to_string(geometry::Point const & p) const -> std::string @@ -1110,12 +1114,15 @@ template<> class Converter { public: - auto from_string(std::string const & s, geometry::Point & p) const -> bool + auto from_string(std::string const & s) const -> std::optional { std::istringstream iss(s); + auto p = geometry::Point(); char comma; iss >> p.x >> comma >> p.y; - return !iss.fail(); + return !iss.fail() + ? std::optional(p) + : std::nullopt; } auto to_string(geometry::Point const & p) const -> std::string