You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by GitBox <gi...@apache.org> on 2021/06/18 20:51:08 UTC

[GitHub] [arrow] bkietz commented on a change in pull request #10551: ARROW-13097: [C++] Provide simple reflection utility

bkietz commented on a change in pull request #10551:
URL: https://github.com/apache/arrow/pull/10551#discussion_r653976569



##########
File path: cpp/src/arrow/util/reflection_test.cc
##########
@@ -0,0 +1,121 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include <gtest/gtest.h>
+
+#include "arrow/util/reflection_internal.h"
+
+namespace arrow {
+namespace internal {
+
+// unmodified structure which we wish to reflect on:
+struct Person {
+  std::string name;
+  int age;
+};
+
+// enumeration of properties:
+template <>
+struct ReflectionTraits<Person> {
+  using Properties = std::tuple<DataMember<Person, int, &Person::age>,

Review comment:
       It was intentional; I wanted to make clear that the ordering follows the trait and not the declaration in the struct. But in practice we'd probably always order identically. I'll switch them

##########
File path: cpp/src/arrow/util/reflection_internal.h
##########
@@ -0,0 +1,192 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <array>
+#include <string>
+#include <tuple>
+#include <utility>
+
+namespace arrow {
+namespace internal {
+
+namespace detail {
+
+#ifdef _MSC_VER
+#define ARROW_PRETTY_FUNCTION __FUNCSIG__
+#else
+#define ARROW_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#endif
+
+template <typename T>
+const char* raw() {
+  return ARROW_PRETTY_FUNCTION;
+}
+
+template <typename T>
+size_t raw_sizeof() {
+  return sizeof(ARROW_PRETTY_FUNCTION);
+}
+
+#undef ARROW_PRETTY_FUNCTION
+
+constexpr bool starts_with(char const* haystack, char const* needle) {
+  return needle[0] == '\0' ||

Review comment:
       Agreed

##########
File path: cpp/src/arrow/util/reflection_internal.h
##########
@@ -0,0 +1,192 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <array>
+#include <string>
+#include <tuple>
+#include <utility>
+
+namespace arrow {
+namespace internal {
+
+namespace detail {
+
+#ifdef _MSC_VER
+#define ARROW_PRETTY_FUNCTION __FUNCSIG__
+#else
+#define ARROW_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#endif
+
+template <typename T>
+const char* raw() {

Review comment:
       https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66639
   Older GCC doesn't think __PRETTY_FUNCTION__ is constexpr. Shame, too: with constexpr it's possible to ensure the sliced-away portions of __PRETTY_FUNCTION__ don't make it into the object file

##########
File path: cpp/src/arrow/util/reflection_internal.h
##########
@@ -0,0 +1,192 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <array>
+#include <string>
+#include <tuple>
+#include <utility>
+
+namespace arrow {
+namespace internal {
+
+namespace detail {
+
+#ifdef _MSC_VER
+#define ARROW_PRETTY_FUNCTION __FUNCSIG__
+#else
+#define ARROW_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#endif
+
+template <typename T>
+const char* raw() {

Review comment:
       https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66639
   Older GCC doesn't think `__PRETTY_FUNCTION__` is constexpr. Shame, too: with constexpr it's possible to ensure the sliced-away portions of `__PRETTY_FUNCTION__` don't make it into the object file

##########
File path: cpp/src/arrow/util/reflection_internal.h
##########
@@ -0,0 +1,192 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <array>
+#include <string>
+#include <tuple>
+#include <utility>
+
+namespace arrow {
+namespace internal {
+
+namespace detail {
+
+#ifdef _MSC_VER
+#define ARROW_PRETTY_FUNCTION __FUNCSIG__
+#else
+#define ARROW_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#endif
+
+template <typename T>
+const char* raw() {
+  return ARROW_PRETTY_FUNCTION;
+}
+
+template <typename T>
+size_t raw_sizeof() {
+  return sizeof(ARROW_PRETTY_FUNCTION);
+}
+
+#undef ARROW_PRETTY_FUNCTION
+
+constexpr bool starts_with(char const* haystack, char const* needle) {
+  return needle[0] == '\0' ||
+         (haystack[0] == needle[0] && starts_with(haystack + 1, needle + 1));
+}
+
+constexpr size_t search(char const* haystack, char const* needle) {
+  return haystack[0] == '\0' || starts_with(haystack, needle)
+             ? 0
+             : search(haystack + 1, needle) + 1;
+}
+
+const size_t typename_prefix = search(raw<double>(), "double");
+
+template <typename T>
+size_t struct_class_prefix() {
+#ifdef _MSC_VER
+  return starts_with(raw<T>() + typename_prefix, "struct ")
+             ? 7
+             : starts_with(raw<T>() + typename_prefix, "class ") ? 6 : 0;
+#else
+  return 0;
+#endif
+}
+
+template <typename T>
+size_t typename_length() {
+  // raw_sizeof<T>() - raw_sizeof<double>() ==
+  //     (length of T's name) - strlen("double")
+  // (length of T's name) ==
+  //     raw_sizeof<T>() - raw_sizeof<double>() + strlen("double")
+  return raw_sizeof<T>() - struct_class_prefix<T>() - raw_sizeof<double>() + 6;

Review comment:
       Sorry, the comment is trying to communicate the algebra of the situation. Pretty function can be thought of as string interpolation, like `"const char* raw<T>() [with T = {}]".format(typename)`. Compilers' format strings differ so we have to compute the length of the extraneous content by using a known typename, for which I chose "double". I know the length of `dbl_len = "const char* raw<T>() [with T = {}]".format('double')` is 6 more than the number of extraneous chars, so `extra_len = dbl_len - 6` which I can subtract from `len("const char* raw<T>() [with T = {}]".format(typename))` to get the length of the type name

##########
File path: cpp/src/arrow/util/reflection_internal.h
##########
@@ -0,0 +1,192 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <array>
+#include <string>
+#include <tuple>
+#include <utility>
+
+namespace arrow {
+namespace internal {
+
+namespace detail {
+
+#ifdef _MSC_VER
+#define ARROW_PRETTY_FUNCTION __FUNCSIG__
+#else
+#define ARROW_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#endif
+
+template <typename T>
+const char* raw() {
+  return ARROW_PRETTY_FUNCTION;
+}
+
+template <typename T>
+size_t raw_sizeof() {
+  return sizeof(ARROW_PRETTY_FUNCTION);
+}
+
+#undef ARROW_PRETTY_FUNCTION
+
+constexpr bool starts_with(char const* haystack, char const* needle) {
+  return needle[0] == '\0' ||
+         (haystack[0] == needle[0] && starts_with(haystack + 1, needle + 1));
+}
+
+constexpr size_t search(char const* haystack, char const* needle) {
+  return haystack[0] == '\0' || starts_with(haystack, needle)
+             ? 0
+             : search(haystack + 1, needle) + 1;
+}
+
+const size_t typename_prefix = search(raw<double>(), "double");
+
+template <typename T>
+size_t struct_class_prefix() {
+#ifdef _MSC_VER
+  return starts_with(raw<T>() + typename_prefix, "struct ")
+             ? 7
+             : starts_with(raw<T>() + typename_prefix, "class ") ? 6 : 0;
+#else
+  return 0;
+#endif
+}
+
+template <typename T>
+size_t typename_length() {
+  // raw_sizeof<T>() - raw_sizeof<double>() ==
+  //     (length of T's name) - strlen("double")
+  // (length of T's name) ==
+  //     raw_sizeof<T>() - raw_sizeof<double>() + strlen("double")
+  return raw_sizeof<T>() - struct_class_prefix<T>() - raw_sizeof<double>() + 6;

Review comment:
       Again, would be much easier to read of I weren't trying to shoehorn this into something c++11 constexpr compatible

##########
File path: cpp/src/arrow/util/reflection_internal.h
##########
@@ -0,0 +1,192 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <array>
+#include <string>
+#include <tuple>
+#include <utility>
+
+namespace arrow {
+namespace internal {
+
+namespace detail {
+
+#ifdef _MSC_VER
+#define ARROW_PRETTY_FUNCTION __FUNCSIG__
+#else
+#define ARROW_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#endif
+
+template <typename T>
+const char* raw() {
+  return ARROW_PRETTY_FUNCTION;
+}
+
+template <typename T>
+size_t raw_sizeof() {
+  return sizeof(ARROW_PRETTY_FUNCTION);
+}
+
+#undef ARROW_PRETTY_FUNCTION
+
+constexpr bool starts_with(char const* haystack, char const* needle) {
+  return needle[0] == '\0' ||
+         (haystack[0] == needle[0] && starts_with(haystack + 1, needle + 1));
+}
+
+constexpr size_t search(char const* haystack, char const* needle) {
+  return haystack[0] == '\0' || starts_with(haystack, needle)
+             ? 0
+             : search(haystack + 1, needle) + 1;
+}
+
+const size_t typename_prefix = search(raw<double>(), "double");
+
+template <typename T>
+size_t struct_class_prefix() {
+#ifdef _MSC_VER
+  return starts_with(raw<T>() + typename_prefix, "struct ")
+             ? 7
+             : starts_with(raw<T>() + typename_prefix, "class ") ? 6 : 0;
+#else
+  return 0;
+#endif
+}
+
+template <typename T>
+size_t typename_length() {
+  // raw_sizeof<T>() - raw_sizeof<double>() ==
+  //     (length of T's name) - strlen("double")
+  // (length of T's name) ==
+  //     raw_sizeof<T>() - raw_sizeof<double>() + strlen("double")
+  return raw_sizeof<T>() - struct_class_prefix<T>() - raw_sizeof<double>() + 6;

Review comment:
       I'll add more comments.




-- 
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.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org