Unverified Commit e2cbb01e authored by Paul Fultz II's avatar Paul Fultz II Committed by GitHub
Browse files

Add support for constructing value from enum (#632)

* Add support for constructing value from enum

* Formatting
parent 63c5582a
......@@ -22,12 +22,14 @@ using bool_c = std::integral_constant<bool, B>;
#ifdef CPPCHECK
#define MIGRAPHX_REQUIRES(...) class = void
#define MIGRAPHX_CLASS_REQUIRES(...) void
#else
#define MIGRAPHX_REQUIRES(...) \
long MIGRAPHX_REQUIRES_VAR() = __LINE__, \
typename std::enable_if<(MIGRAPHX_REQUIRES_VAR() == __LINE__ && \
(migraphx::and_<__VA_ARGS__>{})), \
int>::type = 0
#define MIGRAPHX_CLASS_REQUIRES(...) typename std::enable_if<(migraphx::and_<__VA_ARGS__>{})>::type
#endif
} // namespace MIGRAPHX_INLINE_NS
......
......@@ -85,7 +85,7 @@ value to_value_impl(rank<6>, const T& x)
template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})>
value to_value_impl(rank<7>, const T& x)
{
return static_cast<std::underlying_type_t<T>>(x);
return x;
}
inline value to_value_impl(rank<8>, const std::string& x) { return x; }
......@@ -156,7 +156,7 @@ void from_value_impl(rank<4>, const value& v, T& x)
template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})>
void from_value_impl(rank<5>, const value& v, T& x)
{
x = static_cast<T>(v.to<std::underlying_type_t<T>>());
x = v.to<T>();
}
inline void from_value_impl(rank<6>, const value& v, std::string& x) { x = v.to<std::string>(); }
......
......@@ -19,7 +19,7 @@ inline namespace MIGRAPHX_INLINE_NS {
struct value_base_impl;
template <class To>
template <class To, class = void>
struct value_converter
{
template <class T = To>
......@@ -42,6 +42,17 @@ struct value_converter
}
};
template <class To>
struct value_converter<To, MIGRAPHX_CLASS_REQUIRES(std::is_enum<To>{})>
{
template <class From>
static auto apply(const From& x)
-> decltype(static_cast<To>(value_converter<std::underlying_type_t<To>>::apply(x)))
{
return static_cast<To>(value_converter<std::underlying_type_t<To>>::apply(x));
}
};
template <>
struct value_converter<std::string>
{
......@@ -155,26 +166,29 @@ struct value
MIGRAPHX_VISIT_VALUE_TYPES(MIGRAPHX_VALUE_GENERATE_DECL_METHODS)
template <class T>
using pick = std::conditional_t<
using pick_numeric = std::conditional_t<
std::is_floating_point<T>{},
double,
std::conditional_t<std::is_signed<T>{},
std::int64_t,
std::conditional_t<std::is_unsigned<T>{}, std::uint64_t, T>>>;
template <class T>
using pick = pick_numeric<typename std::conditional_t<std::is_enum<T>{},
std::underlying_type<T>,
std::enable_if<true, T>>::type>;
template <class T>
using is_pickable =
std::integral_constant<bool, (std::is_arithmetic<T>{} and not std::is_pointer<T>{})>;
bool_c<((std::is_arithmetic<T>{} or std::is_enum<T>{}) and not std::is_pointer<T>{})>;
template <class T>
using range_value = std::decay_t<decltype(std::declval<T>().end(), *std::declval<T>().begin())>;
template <class T>
using is_generic_range =
std::integral_constant<bool,
(std::is_convertible<range_value<T>, value>{} and
not std::is_convertible<T, array>{} and
not std::is_convertible<T, object>{})>;
bool_c<(std::is_convertible<range_value<T>, value>{} and
not std::is_convertible<T, array>{} and not std::is_convertible<T, object>{})>;
template <class T, MIGRAPHX_REQUIRES(is_generic_range<T>{})>
value(const T& r) : value(from_values(r))
......@@ -187,11 +201,11 @@ struct value
}
template <class T, MIGRAPHX_REQUIRES(is_pickable<T>{})>
value(T i) : value(pick<T>{i})
value(T i) : value(static_cast<pick<T>>(i))
{
}
template <class T, MIGRAPHX_REQUIRES(is_pickable<T>{})>
value(const std::string& pkey, T i) : value(pkey, pick<T>{i})
value(const std::string& pkey, T i) : value(pkey, static_cast<pick<T>>(i))
{
}
template <class T, class U, class = decltype(value(T{}, U{}))>
......@@ -201,7 +215,7 @@ struct value
template <class T, MIGRAPHX_REQUIRES(is_pickable<T>{})>
value& operator=(T rhs)
{
return *this = pick<T>{rhs}; // NOLINT
return *this = static_cast<pick<T>>(rhs); // NOLINT
}
template <class T, MIGRAPHX_REQUIRES(is_generic_range<T>{})>
value& operator=(T rhs)
......
......@@ -2,6 +2,13 @@
#include <migraphx/float_equal.hpp>
#include <test.hpp>
enum class enum_type
{
a,
b,
c
};
TEST_CASE(value_default_construct)
{
migraphx::value v;
......@@ -65,6 +72,15 @@ TEST_CASE(value_construct_bool)
EXPECT(v.get_key().empty());
}
TEST_CASE(value_construct_enum)
{
migraphx::value v = enum_type::a;
EXPECT(v.is_int64());
EXPECT(v.get_int64() == static_cast<std::uint64_t>(enum_type::a));
EXPECT(bool{v.to<enum_type>() == enum_type::a});
EXPECT(v.get_key().empty());
}
TEST_CASE(value_construct_empty_object)
{
migraphx::value v = migraphx::value::object{};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment