Replace SFINAE with concepts (#5361)

Concepts are cleaner to use and result in much better error messages for incorrect template use.
This commit is contained in:
Tyler Veness
2023-06-07 09:50:09 -07:00
committed by GitHub
parent d57d1a4598
commit 91cbcea841
42 changed files with 397 additions and 361 deletions

View File

@@ -11,7 +11,6 @@
#include <span>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>
@@ -20,6 +19,7 @@
#include "wpi/SmallString.h"
#include "wpi/SmallVector.h"
#include "wpi/StringExtras.h"
#include "wpi/concepts.h"
#include "wpi/mutex.h"
#include "wpi/raw_ostream.h"
@@ -219,9 +219,8 @@ class JArrayRefInner<C, jbyte> {
template <typename C>
class JArrayRefInner<C, jlong> {
public:
template <typename U,
typename = std::enable_if_t<sizeof(U) == sizeof(jlong) &&
std::is_integral_v<U>>>
template <typename U>
requires(sizeof(U) == sizeof(jlong) && std::integral<U>)
operator std::span<const U>() const { // NOLINT
auto arr = static_cast<const C*>(this)->array();
if (arr.empty()) {
@@ -397,46 +396,38 @@ inline jstring MakeJString(JNIEnv* env, std::string_view str) {
// details for MakeJIntArray
namespace detail {
/**
* Slow path (get primitive array and set individual elements).
*
* This is used if the input type is not an integer of the same size (note
* signed/unsigned is ignored).
*/
template <typename T,
bool = (std::is_integral<T>::value && sizeof(jint) == sizeof(T))>
template <typename T>
struct ConvertIntArray {
static jintArray ToJava(JNIEnv* env, std::span<const T> arr) {
jintArray jarr = env->NewIntArray(arr.size());
if (!jarr) {
return nullptr;
if constexpr (sizeof(T) == sizeof(jint) && std::integral<T>) {
// Fast path (use SetIntArrayRegion).
jintArray jarr = env->NewIntArray(arr.size());
if (!jarr) {
return nullptr;
}
env->SetIntArrayRegion(jarr, 0, arr.size(),
reinterpret_cast<const jint*>(arr.data()));
return jarr;
} else {
// Slow path (get primitive array and set individual elements).
//
// This is used if the input type is not an integer of the same size (note
// signed/unsigned is ignored).
jintArray jarr = env->NewIntArray(arr.size());
if (!jarr) {
return nullptr;
}
jint* elements =
static_cast<jint*>(env->GetPrimitiveArrayCritical(jarr, nullptr));
if (!elements) {
return nullptr;
}
for (size_t i = 0; i < arr.size(); ++i) {
elements[i] = static_cast<jint>(arr[i]);
}
env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
return jarr;
}
jint* elements =
static_cast<jint*>(env->GetPrimitiveArrayCritical(jarr, nullptr));
if (!elements) {
return nullptr;
}
for (size_t i = 0; i < arr.size(); ++i) {
elements[i] = static_cast<jint>(arr[i]);
}
env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
return jarr;
}
};
/**
* Fast path (use SetIntArrayRegion).
*/
template <typename T>
struct ConvertIntArray<T, true> {
static jintArray ToJava(JNIEnv* env, std::span<const T> arr) {
jintArray jarr = env->NewIntArray(arr.size());
if (!jarr) {
return nullptr;
}
env->SetIntArrayRegion(jarr, 0, arr.size(),
reinterpret_cast<const jint*>(arr.data()));
return jarr;
}
};
@@ -574,9 +565,9 @@ WPI_JNI_MAKEJARRAY(jdouble, Double)
#undef WPI_JNI_MAKEJARRAY
template <class T, typename = std::enable_if_t<
sizeof(typename T::value_type) == sizeof(jlong) &&
std::is_integral_v<typename T::value_type>>>
template <class T>
requires(sizeof(typename T::value_type) == sizeof(jlong) &&
std::integral<typename T::value_type>)
inline jlongArray MakeJLongArray(JNIEnv* env, const T& arr) {
jlongArray jarr = env->NewLongArray(arr.size());
if (!jarr) {