简体   繁体   English

使用 C++17,我如何创建编译时 map 类型的值?

[英]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);

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM