Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ The below lists features of the `argparse` module that this implementation suppo
* [x] `'+'` (as `one_or_more`)
* [x] `const` (renamed to `const_` due to keyword clash)
* [x] `default` (renamed to `default_` due to keyword clash; only for optional arguments and with no string parsing)
* [x] `type` (built-in (except for `bool`) and user-defined types (via overloading `from_string` function))
* [x] `type` (built-in (except for `bool`) and user-defined types (via specialising `argparse::Converter` class template))
* [x] `choices`
* [x] `required`
* [x] `help`
Expand Down
56 changes: 40 additions & 16 deletions include/argparse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,25 +99,51 @@ namespace argparse
return static_cast<int>(lhs) & static_cast<int>(rhs);
}

inline auto from_string(std::string const & s, auto & t) -> bool
template<typename T>
class Converter
{
auto iss = std::istringstream(s);
iss >> t;
public:
auto from_string(std::string const & s, T & t) const -> bool
{
auto iss = std::istringstream(s);
iss >> t;

return !iss.fail() && (iss.eof() || iss.peek() == std::istringstream::traits_type::eof());
}
return !iss.fail() && (iss.eof() || iss.peek() == std::istringstream::traits_type::eof());
}

auto to_string(T const & t) const -> std::string
{
auto ostr = std::ostringstream();
ostr << t;

return ostr.str();
}

inline auto to_string(auto const & t) -> std::string
auto are_equal(T const & lhs, T const & rhs) const -> bool
{
return lhs == rhs;
}
};

template<typename T>
inline auto from_string(std::string const & s, T & t) -> bool
{
auto ostr = std::ostringstream();
ostr << t;
auto const conv = Converter<T>();
return conv.from_string(s, t);
}

return ostr.str();
template<typename T>
inline auto to_string(T const & t) -> std::string
{
auto const conv = Converter<T>();
return conv.to_string(t);
}

inline auto are_equal(auto const & lhs, auto const & rhs) -> bool
template<typename T>
inline auto are_equal(T const & lhs, T const & rhs) -> bool
{
return lhs == rhs;
auto const conv = Converter<T>();
return conv.are_equal(lhs, rhs);
}

class ArgumentParser
Expand Down Expand Up @@ -520,9 +546,8 @@ namespace argparse
}
else
{
using argparse::from_string;
auto value = T();
if (from_string(string, value))
if (argparse::from_string(string, value))
{
return std::any(value);
}
Expand All @@ -541,14 +566,13 @@ namespace argparse
}
else
{
using argparse::to_string;
return to_string(std::any_cast<T>(value));
return argparse::to_string(std::any_cast<T>(value));
}
}

auto compare(std::any const & lhs, std::any const & rhs) const -> bool override
{
return are_equal(std::any_cast<T>(lhs), std::any_cast<T>(rhs));
return argparse::are_equal(std::any_cast<T>(lhs), std::any_cast<T>(rhs));
}

auto transform(std::vector<std::any> const & values) const -> std::any override
Expand Down
36 changes: 21 additions & 15 deletions test/unittest/custom_a.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CUSTOMA_H
#define CUSTOMA_H

#include "argparse.hpp"
#include <string>


Expand All @@ -20,23 +21,28 @@ namespace foo
};
}

namespace foo
{
inline auto operator==(Custom const & lhs, Custom const & rhs) -> bool
{
return lhs.m_text == rhs.m_text;
}

inline auto from_string(std::string const & s, Custom & c) -> bool
namespace argparse
{
c = Custom(s);
return true;
}

inline auto to_string(Custom const& c) -> std::string
template<>
class Converter<foo::Custom>
{
return "<Custom: " + c.m_text + ">";
}
public:
auto from_string(std::string const & s, foo::Custom & t) const -> bool
{
t = foo::Custom(s);
return true;
}

auto to_string(foo::Custom const & t) const -> std::string
{
return "<Custom: " + t.m_text + ">";
}

auto are_equal(foo::Custom const & lhs, foo::Custom const & rhs) const -> bool
{
return lhs.m_text == rhs.m_text;
}
};
}

#endif /* CUSTOMA_H */
35 changes: 19 additions & 16 deletions test/unittest/custom_b.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef CUSTOMB_H
#define CUSTOMB_H

#include "argparse.hpp"
#include <string>


Expand All @@ -23,23 +24,25 @@ namespace bar
namespace argparse
{
template<>
inline auto from_string(std::string const & s, bar::Custom & c) -> bool
class Converter<bar::Custom>
{
c = bar::Custom(s);
return true;
}

template<>
inline auto to_string(bar::Custom const & t) -> std::string
{
return "<Custom: " + t.m_text + ">";
}

template<>
inline auto are_equal(bar::Custom const & lhs, bar::Custom const & rhs) -> bool
{
return lhs.m_text == rhs.m_text;
}
public:
auto from_string(std::string const & s, bar::Custom & t) const -> bool
{
t = bar::Custom(s);
return true;
}

auto to_string(bar::Custom const & t) const -> std::string
{
return "<Custom: " + t.m_text + ">";
}

auto are_equal(bar::Custom const & lhs, bar::Custom const & rhs) const -> bool
{
return lhs.m_text == rhs.m_text;
}
};
}

#endif /* CUSTOMB_H */
7 changes: 7 additions & 0 deletions test/unittest/test_parsing_optional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

using namespace std::string_literals;

namespace foo
{
inline auto operator==(Custom const & lhs, Custom const & rhs) -> bool
{
return lhs.m_text == rhs.m_text;
}
}
namespace bar
{
inline auto operator==(Custom const & lhs, Custom const & rhs) -> bool
Expand Down
7 changes: 7 additions & 0 deletions test/unittest/test_parsing_positional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@

using namespace std::string_literals;

namespace foo
{
inline auto operator==(Custom const & lhs, Custom const & rhs) -> bool
{
return lhs.m_text == rhs.m_text;
}
}
namespace bar
{
inline auto operator==(Custom const & lhs, Custom const & rhs) -> bool
Expand Down
34 changes: 18 additions & 16 deletions tutorial/custom1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,27 @@ namespace geometry
namespace argparse
{
template<>
inline auto from_string(std::string const & s, geometry::Point & p) -> bool
class Converter<geometry::Point>
{
std::istringstream iss(s);
char comma;
iss >> p.x >> comma >> p.y;
return true;
}
public:
auto from_string(std::string const & s, geometry::Point & p) const -> bool
{
std::istringstream iss(s);
char comma;
iss >> p.x >> comma >> p.y;
return true;
}

template<>
inline auto to_string(geometry::Point const & p) -> std::string
{
return std::to_string(p.x) + "," + std::to_string(p.y);
}
auto to_string(geometry::Point const & p) const -> std::string
{
return std::to_string(p.x) + "," + std::to_string(p.y);
}

template<>
inline auto are_equal(geometry::Point const & l, geometry::Point const & r) -> bool
{
return l.x == r.x && l.y == r.y;
}
auto are_equal(geometry::Point const & l, geometry::Point const & r) const -> bool
{
return l.x == r.x && l.y == r.y;
}
};
}

auto main(int argc, char * argv[]) -> int
Expand Down
34 changes: 18 additions & 16 deletions tutorial/custom2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,27 @@ namespace geometry
namespace argparse
{
template<>
inline auto from_string(std::string const & s, geometry::Point & p) -> bool
class Converter<geometry::Point>
{
std::istringstream iss(s);
char comma;
iss >> p.x >> comma >> p.y;
return !iss.fail();
}
public:
auto from_string(std::string const & s, geometry::Point & p) const -> bool
{
std::istringstream iss(s);
char comma;
iss >> p.x >> comma >> p.y;
return !iss.fail();
}

template<>
inline auto to_string(geometry::Point const & p) -> std::string
{
return std::to_string(p.x) + "," + std::to_string(p.y);
}
auto to_string(geometry::Point const & p) const -> std::string
{
return std::to_string(p.x) + "," + std::to_string(p.y);
}

template<>
inline auto are_equal(geometry::Point const & l, geometry::Point const & r) -> bool
{
return l.x == r.x && l.y == r.y;
}
auto are_equal(geometry::Point const & l, geometry::Point const & r) const -> bool
{
return l.x == r.x && l.y == r.y;
}
};
}

auto main(int argc, char * argv[]) -> int
Expand Down
34 changes: 18 additions & 16 deletions tutorial/custom3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,27 @@ namespace geometry
namespace argparse
{
template<>
inline auto from_string(std::string const & s, geometry::Point & p) -> bool
class Converter<geometry::Point>
{
std::istringstream iss(s);
char comma;
iss >> p.x >> comma >> p.y;
return !iss.fail();
}
public:
auto from_string(std::string const & s, geometry::Point & p) const -> bool
{
std::istringstream iss(s);
char comma;
iss >> p.x >> comma >> p.y;
return !iss.fail();
}

template<>
inline auto to_string(geometry::Point const & p) -> std::string
{
return std::to_string(p.x) + "," + std::to_string(p.y);
}
auto to_string(geometry::Point const & p) const -> std::string
{
return std::to_string(p.x) + "," + std::to_string(p.y);
}

template<>
inline auto are_equal(geometry::Point const & l, geometry::Point const & r) -> bool
{
return l.x == r.x && l.y == r.y;
}
auto are_equal(geometry::Point const & l, geometry::Point const & r) const -> bool
{
return l.x == r.x && l.y == r.y;
}
};
}

auto main(int argc, char * argv[]) -> int
Expand Down
Loading