Skip to content

Commit

Permalink
allow transform to work with arrays. (#349)
Browse files Browse the repository at this point in the history
* allow transform to work with arrays.  The element_type trait required pointer_traits<T> 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.

* fix formatting

* clean up array initialization

* add constexpr array test

* add extra braces to make clang happy
  • Loading branch information
phlptp authored and henryiii committed Nov 30, 2019
1 parent 67dc672 commit 5a25cee
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
11 changes: 7 additions & 4 deletions include/CLI/TypeTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,16 @@ template <> struct IsMemberType<const char *> { 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<T> be valid.
template <typename T> struct element_type {
using type =
typename std::conditional<is_copyable_ptr<T>::value, typename std::pointer_traits<T>::element_type, T>::type;

/// not a pointer
template <typename T, typename Enable = void> struct element_type { using type = T; };

template <typename T> struct element_type<T, typename std::enable_if<is_copyable_ptr<T>::value>::type> {
using type = typename std::pointer_traits<T>::element_type;
};

/// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of
Expand Down
47 changes: 47 additions & 0 deletions tests/TransformTest.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "app_helper.hpp"

#include <array>
#include <unordered_map>

#if defined(CLI11_CPP17)
Expand Down Expand Up @@ -154,6 +155,52 @@ TEST_F(TApp, SimpleNumericalTransformFn) {
EXPECT_EQ(value, 1);
}

TEST_F(TApp, SimpleNumericalTransformFnVector) {
std::vector<std::pair<std::string, int>> conversions{{"one", 1}, {"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<std::pair<std::string, int>, 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));
args = {"-s", "ONe"};
run();
EXPECT_EQ(1u, app.count("-s"));
EXPECT_EQ(1u, opt->count());
EXPECT_EQ(value, 1);
}

// zero copy constexpr array operation with transformer example and test
TEST_F(TApp, SimpleNumericalTransformFnconstexprArray) {
constexpr std::pair<const char *, int> p1{"one", 1};
constexpr std::pair<const char *, int> p2{"two", 2};
constexpr std::array<std::pair<const char *, int>, 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);

args = {"-s", "twO"};
run();
EXPECT_EQ(1u, app.count("-s"));
EXPECT_EQ(1u, opt->count());
EXPECT_EQ(value, 2);
}

TEST_F(TApp, EnumTransformFn) {
enum class test : int16_t { val1 = 3, val2 = 4, val3 = 17 };
test value;
Expand Down

0 comments on commit 5a25cee

Please sign in to comment.