[英]Using C++17, how can I create a compile time map of types to value?
I'm writing a wrapper library that maps real C++ types to Java types for the purposes of JNI.为了 JNI 的目的,我正在编写一个包装器库,它将真正的 C++ 类型映射到 Java 类型。 To map to the right library calls in JNI, I have a series of class specializations:
对于 map 到 JNI 中的正确库调用,我有一系列 class 专业:
template<typename R>
struct call_method_traits;
template<>
struct call_method_traits<void>
{
static constexpr auto value = &JNIEnv::CallVoidMethod;
};
template<>
struct call_method_traits<bool>
{
static constexpr auto value = &JNIEnv::CallBooleanMethod;
};
// etc.....
This is the old-school way to map types to some values, but I'm wondering in C++17 if there is a better way.这是将 map 类型转换为某些值的老式方法,但我想知道 C++17 是否有更好的方法。 At first,
std::tuple
seems promising but it's not an associative type, so I don't see how I can use it for this.起初,
std::tuple
似乎很有希望,但它不是关联类型,所以我不知道如何使用它。
Is the mechanism I'm using still the only way?我使用的机制仍然是唯一的方法吗?
A variable template would be simpler.变量模板会更简单。 But you'd need to introduce some default value for non-specialisation:
但是您需要为非专业化引入一些默认值:
template <class>
static constexpr auto call_method_traits
= nullptr;
template <>
static constexpr auto call_method_traits<void>
= &JNIEnv::CallVoidMethod;
Alternatively, you could keep your trait, and only use the variable template as an alias:或者,您可以保留您的特征,并且仅使用变量模板作为别名:
template <class R>
static constexpr auto call_method_traits_v
= call_method_traits<std::decay_t<R>>::value;
This would allow you to keep the existing API for compatibility, but give users the simpler interface.这将允许您保留现有的 API 以实现兼容性,但为用户提供更简单的界面。
A constexpr template function would be more flexible, and would allow you to for example static_assert
a neat message for the case that has no specialisation. constexpr 模板 function 会更灵活,并且可以让您例如
static_assert
为没有专业化的案例提供简洁的消息。 But it involves a bit more boilerplate.但它涉及更多样板文件。
At first,
std::tuple
seems promising but it's not an associative type, so I don't see how I can use it for this.起初,
std::tuple
似乎很有希望,但它不是关联类型,所以我不知道如何使用它。
Variables template seems more appropriate, but below code shows possible way with std::tuple
:变量模板似乎更合适,但下面的代码显示了
std::tuple
的可能方式:
template <typename T, auto Value>
struct Pair
{
using type = T;
static constexpr auto value = Value;
};
template <typename T, typename Tuple>
struct getter;
template <typename T, auto Value, typename ...Ts>
struct getter<T, std::tuple<Pair<T, Value>, Ts...>>
{
static constexpr auto value = Value;
};
template <typename T, typename T2, auto Value, typename ...Ts>
struct getter<T, std::tuple<Pair<T2, Value>, Ts...>> : getter<T, std::tuple<Ts...>>
{
};
// You might also provide specialization for getter<T, std::tuple<>>
// to handle case "not present".
And then, possible usage:然后,可能的用法:
using Pairs = std::tuple<Pair<void, &JNIEnv::CallVoidMethod>,
Pair<bool, &JNIEnv::CallBooleanMethod>
/*..*/
>;
static_assert(getter<void, Pairs>::value == &JNIEnv::CallVoidMethod);
static_assert(getter<bool, Pairs>::value == &JNIEnv::CallBooleanMethod);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.