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>; ...@@ -22,12 +22,14 @@ using bool_c = std::integral_constant<bool, B>;
#ifdef CPPCHECK #ifdef CPPCHECK
#define MIGRAPHX_REQUIRES(...) class = void #define MIGRAPHX_REQUIRES(...) class = void
#define MIGRAPHX_CLASS_REQUIRES(...) void
#else #else
#define MIGRAPHX_REQUIRES(...) \ #define MIGRAPHX_REQUIRES(...) \
long MIGRAPHX_REQUIRES_VAR() = __LINE__, \ long MIGRAPHX_REQUIRES_VAR() = __LINE__, \
typename std::enable_if<(MIGRAPHX_REQUIRES_VAR() == __LINE__ && \ typename std::enable_if<(MIGRAPHX_REQUIRES_VAR() == __LINE__ && \
(migraphx::and_<__VA_ARGS__>{})), \ (migraphx::and_<__VA_ARGS__>{})), \
int>::type = 0 int>::type = 0
#define MIGRAPHX_CLASS_REQUIRES(...) typename std::enable_if<(migraphx::and_<__VA_ARGS__>{})>::type
#endif #endif
} // namespace MIGRAPHX_INLINE_NS } // namespace MIGRAPHX_INLINE_NS
......
...@@ -85,7 +85,7 @@ value to_value_impl(rank<6>, const T& x) ...@@ -85,7 +85,7 @@ value to_value_impl(rank<6>, const T& x)
template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})> template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})>
value to_value_impl(rank<7>, const T& x) 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; } 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) ...@@ -156,7 +156,7 @@ void from_value_impl(rank<4>, const value& v, T& x)
template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})> template <class T, MIGRAPHX_REQUIRES(std::is_enum<T>{})>
void from_value_impl(rank<5>, const value& v, T& x) 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>(); } 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 { ...@@ -19,7 +19,7 @@ inline namespace MIGRAPHX_INLINE_NS {
struct value_base_impl; struct value_base_impl;
template <class To> template <class To, class = void>
struct value_converter struct value_converter
{ {
template <class T = To> template <class T = To>
...@@ -42,6 +42,17 @@ struct value_converter ...@@ -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 <> template <>
struct value_converter<std::string> struct value_converter<std::string>
{ {
...@@ -155,26 +166,29 @@ struct value ...@@ -155,26 +166,29 @@ struct value
MIGRAPHX_VISIT_VALUE_TYPES(MIGRAPHX_VALUE_GENERATE_DECL_METHODS) MIGRAPHX_VISIT_VALUE_TYPES(MIGRAPHX_VALUE_GENERATE_DECL_METHODS)
template <class T> template <class T>
using pick = std::conditional_t< using pick_numeric = std::conditional_t<
std::is_floating_point<T>{}, std::is_floating_point<T>{},
double, double,
std::conditional_t<std::is_signed<T>{}, std::conditional_t<std::is_signed<T>{},
std::int64_t, std::int64_t,
std::conditional_t<std::is_unsigned<T>{}, std::uint64_t, 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> template <class T>
using is_pickable = 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> template <class T>
using range_value = std::decay_t<decltype(std::declval<T>().end(), *std::declval<T>().begin())>; using range_value = std::decay_t<decltype(std::declval<T>().end(), *std::declval<T>().begin())>;
template <class T> template <class T>
using is_generic_range = using is_generic_range =
std::integral_constant<bool, bool_c<(std::is_convertible<range_value<T>, value>{} and
(std::is_convertible<range_value<T>, value>{} and not std::is_convertible<T, array>{} and not std::is_convertible<T, object>{})>;
not std::is_convertible<T, array>{} and
not std::is_convertible<T, object>{})>;
template <class T, MIGRAPHX_REQUIRES(is_generic_range<T>{})> template <class T, MIGRAPHX_REQUIRES(is_generic_range<T>{})>
value(const T& r) : value(from_values(r)) value(const T& r) : value(from_values(r))
...@@ -187,11 +201,11 @@ struct value ...@@ -187,11 +201,11 @@ struct value
} }
template <class T, MIGRAPHX_REQUIRES(is_pickable<T>{})> 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>{})> 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{}))> template <class T, class U, class = decltype(value(T{}, U{}))>
...@@ -201,7 +215,7 @@ struct value ...@@ -201,7 +215,7 @@ struct value
template <class T, MIGRAPHX_REQUIRES(is_pickable<T>{})> template <class T, MIGRAPHX_REQUIRES(is_pickable<T>{})>
value& operator=(T rhs) 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>{})> template <class T, MIGRAPHX_REQUIRES(is_generic_range<T>{})>
value& operator=(T rhs) value& operator=(T rhs)
......
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
#include <migraphx/float_equal.hpp> #include <migraphx/float_equal.hpp>
#include <test.hpp> #include <test.hpp>
enum class enum_type
{
a,
b,
c
};
TEST_CASE(value_default_construct) TEST_CASE(value_default_construct)
{ {
migraphx::value v; migraphx::value v;
...@@ -65,6 +72,15 @@ TEST_CASE(value_construct_bool) ...@@ -65,6 +72,15 @@ TEST_CASE(value_construct_bool)
EXPECT(v.get_key().empty()); 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) TEST_CASE(value_construct_empty_object)
{ {
migraphx::value v = migraphx::value::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