bkietz commented on code in PR #14827:
URL: https://github.com/apache/arrow/pull/14827#discussion_r1048994714
##########
cpp/src/arrow/util/reflection_internal.h:
##########
@@ -91,21 +92,260 @@ PropertyTuple<Properties...> MakeProperties(Properties...
props) {
return {std::make_tuple(props...)};
}
+/// Returns a string_view containing the name of a value.
+template <auto>
+constexpr std::string_view nameof(bool include_leading_k = false);
+
+/// Returns a string_view containing the (unqualified) name of a type.
+template <typename>
+constexpr std::string_view nameof();
+
+/// Returns a string_view containing the name of an enumeration member.
+template <typename Enum>
+constexpr std::string_view enum_name(Enum e, bool include_leading_k = false);
+
+/// Returns the enumeration member corresponding to name, or
+/// nullopt if name doesn't correspond to an enum member.
template <typename Enum>
-struct EnumTraits {};
+constexpr std::optional<Enum> enum_cast(std::string_view name);
+
+/// Returns the enumeration member corresponding to an integer, or
+/// nullopt if the integer doesn't correspond to an enum member.
+template <typename Enum, typename Int>
+constexpr auto enum_cast(Int i) ->
std::optional<decltype(static_cast<Enum>(i))>;
+
+namespace impl {
+template <auto V>
+constexpr std::string_view pretty_function() {
+#ifdef _MSC_VER
+ return __FUNCSIG__;
+#else
+ return __PRETTY_FUNCTION__;
+#endif
+}
+
+template <typename T>
+constexpr std::string_view pretty_function() {
+#ifdef _MSC_VER
+ return __FUNCSIG__;
+#else
+ return __PRETTY_FUNCTION__;
+#endif
+}
+
+constexpr auto kValueNamePrefixSuffix = [] {
+ size_t prefix{}, suffix{};
+
+ auto raw = pretty_function<2234527>();
+ if (prefix = raw.find("2234527"); prefix != std::string_view::npos) {
+ suffix = raw.size() - prefix - std::string_view{"2234527"}.size();
+ } else {
+ // some compilers render hexadecimal integer template arguments
+ raw = pretty_function<0x346243>();
+ prefix = raw.find("0x346243");
+ suffix = raw.size() - prefix - std::string_view{"0x346243"}.size();
+ }
+
+ return std::pair{prefix, suffix};
+}();
+
+constexpr auto kTypeNamePrefixSuffix = [] {
+ auto raw = pretty_function<double>();
+ size_t prefix = raw.find("double");
+ size_t suffix = raw.size() - prefix - std::string_view{"double"}.size();
+ return std::pair{prefix, suffix};
+}();
+
+/// std::array is not constexpr in all STL impls
+template <typename T, size_t N>
+class array {
+ public:
+ constexpr array() = default;
-template <typename Enum, Enum... Values>
-struct BasicEnumTraits {
- using CType = typename std::underlying_type<Enum>::type;
- using Type = typename CTypeTraits<CType>::ArrowType;
- static std::array<Enum, sizeof...(Values)> values() { return {Values...}; }
+ constexpr explicit array(const T* ptr) {
+ for (T& value : values_) {
+ value = *ptr++;
+ }
+ }
+
+ constexpr explicit array(const T (&arr)[N]) // NOLINT
+ : array{static_cast<const T*>(arr)} {}
+
+ [[nodiscard]] static constexpr size_t size() { return N; }
+ [[nodiscard]] constexpr const T* data() const { return values_; }
+ [[nodiscard]] constexpr T* data() { return values_; }
+ [[nodiscard]] constexpr const T* begin() const { return values_; }
+ [[nodiscard]] constexpr const T* end() const { return begin() + N; }
+ [[nodiscard]] constexpr const T& operator[](size_t i) const { return
begin()[i]; }
+
+ private:
+ T values_[N] = {}; // NOLINT
};
-template <typename T, typename Enable = void>
-struct has_enum_traits : std::false_type {};
+template <typename T, size_t N, size_t M>
+constexpr bool operator==(const array<T, N>& l, const array<T, M>& r) {
+ if constexpr (N != M) {
+ return false;
+ } else {
+ for (size_t i = 0; i < N; ++i) {
+ if (l[i] != r[i]) return false;
+ }
+ return true;
+ }
+}
+
+template <typename T, size_t N, typename R>
+constexpr bool operator!=(const array<T, N>& l, const R& r) {
+ return !(l == r);
+}
+
+template <auto...>
+struct sequence {};
+
+constexpr std::string_view TrimNamespace(std::string_view name) {
+ for (size_t i = name.size(); i != 0; --i) {
+ char c = name[i - 1];
+ if ('A' <= c && c <= 'Z') continue;
+ if ('a' <= c && c <= 'z') continue;
+ if ('0' <= c && c <= '9') continue;
+ if (c == '_') continue;
+ name = name.substr(i);
+ break;
+ }
+ return name;
+}
+
+template <auto Value>
+constexpr auto kValueNameStorage = [] {
+ constexpr std::string_view name = [] {
+ std::string_view name = pretty_function<Value>();
+ auto [prefix, suffix] = kValueNamePrefixSuffix;
+ name.remove_prefix(prefix);
+ name.remove_suffix(suffix);
+ name = TrimNamespace(name);
+ return name;
+ }();
+
+ // copying out of the string_view here ensures that characters which were
+ // sliced out are not present in (release)binaries
+ return array<char, name.size()>{name.data()};
+}();
template <typename T>
-struct has_enum_traits<T, void_t<typename EnumTraits<T>::Type>> :
std::true_type {};
+constexpr auto kTypeNameStorage = [] {
+ constexpr std::string_view name = [] {
+ std::string_view name = pretty_function<T>();
+ auto [prefix, suffix] = kTypeNamePrefixSuffix;
+ name.remove_prefix(prefix);
+ name.remove_suffix(suffix);
+ return TrimNamespace(name);
+ }();
+ return array<char, name.size()>{name.data()};
+}();
-} // namespace internal
-} // namespace arrow
+template <typename Enum, int I, Enum E = static_cast<Enum>(I)>
+constexpr bool IsValidEnumMember() {
+ return kValueNameStorage<E>[0] < '0' || kValueNameStorage<E>[0] > '9';
+}
+
+template <typename Enum,
+ typename Limits = std::numeric_limits<std::underlying_type_t<Enum>>,
+ int I = Limits::min(), int Max = Limits::max(), Enum... Members>
+struct DefaultEnumMembers;
+
+template <typename Enum, typename Limits, int Max, Enum... Members>
+struct DefaultEnumMembers<Enum, Limits, Max, Max, Members...> {
+ using members = sequence<Members...>;
+};
+
+template <typename Enum, typename Limits, int I, int Max, Enum... Members>
+struct DefaultEnumMembers
+ : std::conditional_t<
+ IsValidEnumMember<Enum, I>(),
+ DefaultEnumMembers<Enum, Limits, I + 1, Max, Members...,
static_cast<Enum>(I)>,
+ DefaultEnumMembers<Enum, Limits, I + 1, Max, Members...>> {};
Review Comment:
That's why this is limited to enumerations which are only one byte wide, so
we'll do a maximum of 256 iterations per enum. I wouldn't expect that to have a
heavy compile time cost
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]