From 100968311fdf94f60b69a62bec908300917c8061 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Tue, 26 Nov 2019 07:02:22 -0800 Subject: [PATCH 1/5] allow transform to work with arrays. The element_type trait required pointer_traits to be defined for the type which it was for vector but not for array due to decay rules in C++, even though it was not used. So Element type had to be split into two templates instead of a conditional. --- include/CLI/TypeTools.hpp | 10 +++++++--- tests/TransformTest.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp index bb9211d88..f2313010c 100644 --- a/include/CLI/TypeTools.hpp +++ b/include/CLI/TypeTools.hpp @@ -74,13 +74,17 @@ template <> struct IsMemberType { using type = std::string; }; namespace detail { -// These are utilities for IsMember +// These are utilities for IsMember and other transforming objects /// Handy helper to access the element_type generically. This is not part of is_copyable_ptr because it requires that /// pointer_traits be valid. -template struct element_type { + +/// not a pointer +template struct element_type { using type = T; }; + +template struct element_type::value>::type> { using type = - typename std::conditional::value, typename std::pointer_traits::element_type, T>::type; + typename std::pointer_traits::element_type; }; /// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of diff --git a/tests/TransformTest.cpp b/tests/TransformTest.cpp index c85b541e6..49eabfebb 100644 --- a/tests/TransformTest.cpp +++ b/tests/TransformTest.cpp @@ -1,5 +1,6 @@ #include "app_helper.hpp" +#include #include #if defined(CLI11_CPP17) @@ -154,6 +155,31 @@ TEST_F(TApp, SimpleNumericalTransformFn) { EXPECT_EQ(value, 1); } +TEST_F(TApp, SimpleNumericalTransformFnVector) { + std::vector> conversions{std::make_pair(std::string("one"), 1), + std::make_pair(std::string("two"), 2)}; + int value; + auto opt = app.add_option("-s", value)->transform(CLI::Transformer(conversions, CLI::ignore_case)); + args = {"-s", "ONe"}; + run(); + EXPECT_EQ(1u, app.count("-s")); + EXPECT_EQ(1u, opt->count()); + EXPECT_EQ(value, 1); +} + +TEST_F(TApp, SimpleNumericalTransformFnArray) { + std::array, 2> conversions{std::make_pair(std::string("one"), 1), + std::make_pair(std::string("two"), 2)}; + + int value; + auto opt = app.add_option("-s", value)->transform(CLI::Transformer(conversions, CLI::ignore_case)); + args = {"-s", "ONe"}; + run(); + EXPECT_EQ(1u, app.count("-s")); + EXPECT_EQ(1u, opt->count()); + EXPECT_EQ(value, 1); +} + TEST_F(TApp, EnumTransformFn) { enum class test : int16_t { val1 = 3, val2 = 4, val3 = 17 }; test value; From 3bab24566f038ac637edd26f18a670d29f59b1f6 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Tue, 26 Nov 2019 07:16:21 -0800 Subject: [PATCH 2/5] fix formatting --- include/CLI/TypeTools.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp index f2313010c..cd4aabc5a 100644 --- a/include/CLI/TypeTools.hpp +++ b/include/CLI/TypeTools.hpp @@ -83,8 +83,7 @@ namespace detail { template struct element_type { using type = T; }; template struct element_type::value>::type> { - using type = - typename std::pointer_traits::element_type; + using type = typename std::pointer_traits::element_type; }; /// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of From a90a45b81385a84d5c712d4e19d009b15c6c6f48 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Tue, 26 Nov 2019 07:28:12 -0800 Subject: [PATCH 3/5] clean up array initialization --- tests/TransformTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/TransformTest.cpp b/tests/TransformTest.cpp index 49eabfebb..5d06dc67c 100644 --- a/tests/TransformTest.cpp +++ b/tests/TransformTest.cpp @@ -156,8 +156,7 @@ TEST_F(TApp, SimpleNumericalTransformFn) { } TEST_F(TApp, SimpleNumericalTransformFnVector) { - std::vector> conversions{std::make_pair(std::string("one"), 1), - std::make_pair(std::string("two"), 2)}; + std::vector> conversions{{"one", 1}, {"two", 2}}; int value; auto opt = app.add_option("-s", value)->transform(CLI::Transformer(conversions, CLI::ignore_case)); args = {"-s", "ONe"}; @@ -168,8 +167,9 @@ TEST_F(TApp, SimpleNumericalTransformFnVector) { } TEST_F(TApp, SimpleNumericalTransformFnArray) { - std::array, 2> conversions{std::make_pair(std::string("one"), 1), - std::make_pair(std::string("two"), 2)}; + std::array, 2> conversions; + conversions[0] = std::make_pair(std::string("one"), 1); + conversions[1] = std::make_pair(std::string("two"), 2); int value; auto opt = app.add_option("-s", value)->transform(CLI::Transformer(conversions, CLI::ignore_case)); From 1665af2d764d233f3678d83cb7ae3a1a7356685c Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 30 Nov 2019 06:44:21 -0800 Subject: [PATCH 4/5] add constexpr array test --- tests/TransformTest.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/TransformTest.cpp b/tests/TransformTest.cpp index 5d06dc67c..0733e974c 100644 --- a/tests/TransformTest.cpp +++ b/tests/TransformTest.cpp @@ -180,6 +180,21 @@ TEST_F(TApp, SimpleNumericalTransformFnArray) { EXPECT_EQ(value, 1); } +// zero copy constexpr array operation with transformer example and test +TEST_F(TApp, SimpleNumericalTransformFnconstexprArray) { + constexpr std::pair p1{"one", 1}; + constexpr std::pair p2{"two", 2}; + constexpr std::array, 2> conversions_c{p1, p2}; + + int value; + auto opt = app.add_option("-s", value)->transform(CLI::Transformer(&conversions_c, CLI::ignore_case)); + args = {"-s", "ONe"}; + run(); + EXPECT_EQ(1u, app.count("-s")); + EXPECT_EQ(1u, opt->count()); + EXPECT_EQ(value, 1); +} + TEST_F(TApp, EnumTransformFn) { enum class test : int16_t { val1 = 3, val2 = 4, val3 = 17 }; test value; From 80947f0eb95fb4074652433c365838bbb77fc4d3 Mon Sep 17 00:00:00 2001 From: Philip Top Date: Sat, 30 Nov 2019 07:06:53 -0800 Subject: [PATCH 5/5] add extra braces to make clang happy --- tests/TransformTest.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/TransformTest.cpp b/tests/TransformTest.cpp index 0733e974c..25fd9fea0 100644 --- a/tests/TransformTest.cpp +++ b/tests/TransformTest.cpp @@ -184,7 +184,7 @@ TEST_F(TApp, SimpleNumericalTransformFnArray) { TEST_F(TApp, SimpleNumericalTransformFnconstexprArray) { constexpr std::pair p1{"one", 1}; constexpr std::pair p2{"two", 2}; - constexpr std::array, 2> conversions_c{p1, p2}; + constexpr std::array, 2> conversions_c{{p1, p2}}; int value; auto opt = app.add_option("-s", value)->transform(CLI::Transformer(&conversions_c, CLI::ignore_case)); @@ -193,6 +193,12 @@ TEST_F(TApp, SimpleNumericalTransformFnconstexprArray) { EXPECT_EQ(1u, app.count("-s")); EXPECT_EQ(1u, opt->count()); EXPECT_EQ(value, 1); + + args = {"-s", "twO"}; + run(); + EXPECT_EQ(1u, app.count("-s")); + EXPECT_EQ(1u, opt->count()); + EXPECT_EQ(value, 2); } TEST_F(TApp, EnumTransformFn) {