Skip to content

Commit

Permalink
Update some metafunctions for increased portability.
Browse files Browse the repository at this point in the history
As the matrix of supported compilers an increasing number of compiler inconsistencies are unfortunately showing, both across clang and gcc, but also across platforms (mac and Linux) and versions (C++17 and C++20).

gcc does not seem to permit template specialisations within class definitions so inner helper classes have been moved out of classes (despite the current form being cleaner).

Also, gcc seems to take issue with using declarations that shadow types in the outer namespace, so they have been modified with a leading "_", e.g. "using _ExposedType = ...".

#42

Tested: Compiled on Ubuntu and Mac platforms with C++20 using clang and gcc.
PiperOrigin-RevId: 711515926
  • Loading branch information
jwhpryor authored and copybara-github committed Jan 11, 2025
1 parent 635e151 commit 520b8d0
Show file tree
Hide file tree
Showing 13 changed files with 139 additions and 134 deletions.
8 changes: 1 addition & 7 deletions implementation/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,15 @@ cc_library(
name = "array_ref",
hdrs = ["array_ref.h"],
deps = [
":array",
":array_view",
":class",
":class_ref",
":default_class_loader",
":forward_declarations",
":jni_type",
":local_object",
":object_ref",
":no_idx",
":promotion_mechanics_tags",
":ref_base",
"//:jni_dep",
"//implementation/jni_helper:jni_array_helper",
"//implementation/jni_helper:lifecycle",
"//implementation/jni_helper:lifecycle_object",
],
)

Expand Down
13 changes: 6 additions & 7 deletions implementation/array_ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@

// IWYU pragma: private, include "third_party/jni_wrapper/jni_bind.h"

#include <atomic>
#include <cstddef>
#include <type_traits>

#include "implementation/array_view.h"
#include "implementation/class_ref.h"
#include "implementation/forward_declarations.h"
#include "implementation/jni_helper/jni_array_helper.h"
#include "implementation/jni_helper/lifecycle.h"
#include "implementation/local_object.h"
#include "implementation/no_idx.h"
#include "implementation/promotion_mechanics_tags.h"
#include "jni_dep.h"

Expand All @@ -50,10 +53,6 @@ class ArrayRef : public ScopedArrayImpl<JniT> {
: Base(AdoptLocal{},
JniArrayHelper<SpanType, JniT::kRank>::NewArray(size)) {}

template <typename T>
ArrayRef(const ArrayViewHelper<T>& array_view_helper)
: Base(AdoptLocal{}, array_view_helper.val) {}

explicit ArrayRef(int size) : ArrayRef(static_cast<std::size_t>(size)) {}

ArrayView<SpanType, JniT::kRank> Pin(bool copy_on_completion = true) {
Expand Down Expand Up @@ -133,9 +132,9 @@ class ArrayRef<
// e.g.
// LocalArray arr { 5, LocalObject<kClass> {args...} };
// LocalArray arr { 5, GlobalObject<kClass> {args...} };
template <template <const auto&, const auto&, const auto&>
class ObjectContainer,
const auto& class_v, const auto& class_loader_v, const auto& jvm_v>
template <
template <const auto&, const auto&, const auto&> class ObjectContainer,
const auto& class_v, const auto& class_loader_v, const auto& jvm_v>
ArrayRef(std::size_t size,
const ObjectContainer<class_v, class_loader_v, jvm_v>& obj)
: ArrayRef(size, static_cast<jobject>(obj)) {}
Expand Down
32 changes: 17 additions & 15 deletions implementation/array_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,22 @@ class ArrayView {
const std::size_t size_;
};

// Metafunction that returns the type after a single dereference.
template <typename SpanType, std::size_t>
struct PinHelper {
using type = jobjectArray;
};

template <typename SpanType>
struct PinHelper<SpanType, 2> {
using type = RegularToArrayTypeMap_t<SpanType>;
};

template <typename SpanType>
struct PinHelper<SpanType, 1> {
using type = jobject;
};

// Object arrays, or arrays with rank > 1 (which are object arrays), or strings.
template <typename SpanType_, std::size_t kRank>
class ArrayView<
Expand All @@ -130,21 +146,7 @@ class ArrayView<
public:
using SpanType = SpanType_;

// Metafunction that returns the type after a single dereference.
template <std::size_t>
struct PinHelper {
using type = jobjectArray;
};
template <>
struct PinHelper<2> {
using type = RegularToArrayTypeMap_t<SpanType>;
};
template <>
struct PinHelper<1> {
using type = jobject;
};

using PinHelper_t = typename PinHelper<kRank>::type;
using PinHelper_t = typename PinHelper<SpanType_, kRank>::type;

struct Iterator {
using iterator_category = std::random_access_iterator_tag;
Expand Down
11 changes: 8 additions & 3 deletions implementation/jvm_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

#include <cstddef>

#include <gtest/gtest.h>
#include "jni_bind.h"

Expand All @@ -39,16 +41,19 @@ TEST(Jni, JvmStaticClassLoaderLookupsWork) {
SupportedClassSet{}};

static constexpr Jvm kJvm1{kClassLoader1};
static_assert(kJvm1.IdxOfClassLoader<kUnusedLoader>() == -1);
static_assert(kJvm1.IdxOfClassLoader<kUnusedLoader>() ==
static_cast<size_t>(-1));
static_assert(kJvm1.IdxOfClassLoader<kClassLoader1>() == 0);

static constexpr Jvm kJvm2{kClassLoader1, kClassLoader2};
static_assert(kJvm2.IdxOfClassLoader<kUnusedLoader>() == -1);
static_assert(kJvm2.IdxOfClassLoader<kUnusedLoader>() ==
static_cast<size_t>(-1));
static_assert(kJvm2.IdxOfClassLoader<kClassLoader1>() == 0);
static_assert(kJvm2.IdxOfClassLoader<kClassLoader2>() == 1);

static constexpr Jvm kJvm3{kClassLoader1, kClassLoader2, kClassLoader3};
static_assert(kJvm3.IdxOfClassLoader<kUnusedLoader>() == -1);
static_assert(kJvm3.IdxOfClassLoader<kUnusedLoader>() ==
static_cast<size_t>(-1));
static_assert(kJvm3.IdxOfClassLoader<kClassLoader1>() == 0);
static_assert(kJvm3.IdxOfClassLoader<kClassLoader2>() == 1);
static_assert(kJvm3.IdxOfClassLoader<kClassLoader3>() == 2);
Expand Down
32 changes: 16 additions & 16 deletions implementation/selector_static_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ struct Ancestor<IdT, 0> {
template <typename IdT, std::size_t I>
using Ancestor_t = typename Ancestor<IdT, I>::type;

template <std::size_t I>
struct IthRawTypeMember {
template <typename T>
static constexpr const auto& Val(const T& val) {
return IthRawTypeMember<I - 1>::Val(val.raw_);
}
};

template <>
struct IthRawTypeMember<0> {
template <typename T>
static constexpr const auto& Val(const T& val) {
return val;
}
};

// Helper to generate full signature information for a "selected" value, and
// possibly some container information. Here, |Selector| is |MethodSelection|,
// |FieldSelection|, etc.
Expand All @@ -73,22 +89,6 @@ struct SelectorStaticInfo {
using Selector =
ParentIfSelf_t<kIsSelf, Ancestor_t<SelectorIn, SelectorIn::kAncestorIdx>>;

template <std::size_t I>
struct IthRawTypeMember {
template <typename T>
static constexpr const auto& Val(const T& val) {
return IthRawTypeMember<I - 1>::Val(val.raw_);
}
};

template <>
struct IthRawTypeMember<0> {
template <typename T>
static constexpr const auto& Val(const T& val) {
return val;
}
};

// Strangely, the compiler refuses to peer through Val and loses the
// constexpr-ness (i.e std::decay_t<decltype(Val())>; is not a constant
// expression).
Expand Down
2 changes: 1 addition & 1 deletion javatests/com/jnibind/test/modulo.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ T Modulo(std::size_t increment_count, T val = T{0},
T max = std::numeric_limits<T>::max()) {
T ret = val;

for (int i = 0; i < increment_count; ++i) {
for (std::size_t i = 0; i < increment_count; ++i) {
ret += T{1};
while (ret >= max) {
ret -= max;
Expand Down
1 change: 1 addition & 0 deletions metaprogramming/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,7 @@ cc_test(
cc_library(
name = "queryable_map",
hdrs = ["queryable_map.h"],
tags = ["manual"],
deps = [
":interleave",
":tuple_from_size",
Expand Down
46 changes: 24 additions & 22 deletions metaprogramming/cartesian_product.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,44 +53,46 @@ struct GenerateBitSequenceFromTupSets {
};
};

// Due to a gcc bug, this requires using a name that is *not* type.
template <typename... Tups>
using type = typename Helper<Tups...>::template SequenceGenerator<
using generated_type = typename Helper<Tups...>::template SequenceGenerator<
std::make_index_sequence<sizeof...(Tups)>>::type;
};

struct GenerateBitSequenceFromTupSetsFunc {
template <typename... Tups>
using type = typename GenerateBitSequenceFromTupSets::template type<Tups...>;
using generated_type =
typename GenerateBitSequenceFromTupSets::template generated_type<Tups...>;
};

template <typename... Tups>
using GenerateBitSequenceFromTupSets_t =
typename GenerateBitSequenceFromTupSets::template type<Tups...>;
typename GenerateBitSequenceFromTupSets::template generated_type<Tups...>;

struct CartesianProduct {
template <typename... Tups>
struct CartesianProductHelper {
using NBitSequenceForTups = GenerateBitSequenceFromTupSets_t<Tups...>;
using AllTupsAsList = std::tuple<Tups...>;

template <typename>
struct SequenceGenerator {};
template <typename... Tups>
struct CartesianProductHelper {
using NBitSequenceForTups = GenerateBitSequenceFromTupSets_t<Tups...>;
using AllTupsAsList = std::tuple<Tups...>;

template <size_t... Is>
struct SequenceGenerator<std::index_sequence<Is...>> {
using type = std::tuple<typename Increment_t<
NBitSequenceForTups, Is>::TypeMask::template type<AllTupsAsList>...>;
};
template <typename>
struct SequenceGenerator {};

using type = typename SequenceGenerator<std::make_index_sequence<
NBitSequenceForTups::max_representable_size_>>::type;
template <size_t... Is>
struct SequenceGenerator<std::index_sequence<Is...>> {
using type = std::tuple<typename Increment_t<
NBitSequenceForTups, Is>::TypeMask::template type<AllTupsAsList>...>;
};

template <>
struct CartesianProductHelper<> {
using type = std::tuple<>;
};
using type = typename SequenceGenerator<std::make_index_sequence<
NBitSequenceForTups::max_representable_size_>>::type;
};

template <>
struct CartesianProductHelper<> {
using type = std::tuple<>;
};

struct CartesianProduct {
template <typename... Tups>
using type = typename CartesianProductHelper<Tups...>::type;
};
Expand Down
56 changes: 23 additions & 33 deletions metaprogramming/even_odd.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,35 @@

namespace jni::metaprogramming {

// Metafunction to return only even elements.
struct Even {
template <typename... Ts>
struct EvenHelper {};
template <typename... Ts>
struct EvenHelper {};

template <>
struct EvenHelper<std::tuple<>> {
using type = std::tuple<>;
};
template <>
struct EvenHelper<std::tuple<>> {
using type = std::tuple<>;
};

template <typename... Ts>
struct OddHelper {};
template <typename... Ts>
struct OddHelper {};

template <>
struct OddHelper<std::tuple<>> {
using type = std::tuple<>;
};
template <>
struct OddHelper<std::tuple<>> {
using type = std::tuple<>;
};

template <typename T, typename... Ts>
struct OddHelper<std::tuple<T, Ts...>> {
using type = typename EvenHelper<std::tuple<Ts...>>::type;
};
template <typename T, typename... Ts>
struct EvenHelper<std::tuple<T, Ts...>> {
using type = ConcatenateTup_t<std::tuple<T>,
typename OddHelper<std::tuple<Ts...>>::type>;
};

template <typename T, typename... Ts>
struct EvenHelper<std::tuple<T, Ts...>> {
using type = ConcatenateTup_t<std::tuple<T>,
typename OddHelper<std::tuple<Ts...>>::type>;
};
template <typename T, typename... Ts>
struct OddHelper<std::tuple<T, Ts...>> {
using type = typename EvenHelper<std::tuple<Ts...>>::type;
};

// Metafunction to return only even elements.
struct Even {
template <typename... Ts>
using type = typename EvenHelper<std::tuple<Ts...>>::type;
};
Expand All @@ -61,16 +61,6 @@ using Even_t = typename Even::template type<Ts...>;

// Metafunction to return only odd elements.
struct Odd {
template <typename... Ts>
struct OddHelper {
using type = std::tuple<>;
};

template <typename T, typename... Ts>
struct OddHelper<std::tuple<T, Ts...>> {
using type = Even_t<Ts...>;
};

template <typename... Ts>
using type = typename OddHelper<std::tuple<Ts...>>::type;
};
Expand Down
2 changes: 2 additions & 0 deletions metaprogramming/lambda_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ struct StringAsType : StringAsTypeBase {

template <typename Identifier, std::size_t... I>
constexpr auto LambdaToStr(Identifier id, std::index_sequence<I...>) {
// This stifles an incorrect compiler warning on gcc.
static_assert(!std::is_same_v<void, decltype(id)>);
return StringAsType<id()[I]...>{};
}

Expand Down
Loading

0 comments on commit 520b8d0

Please sign in to comment.