c++ - 简明双向静态1 :1 mapping of values and types

标签 c++ templates c++17 template-meta-programming c++20

我将从我想象如何使用我想创建的代码开始。它不必完全像这样,但它是我在标题中所说的“简洁”的一个很好的例子。就我而言,它是将类型映射到相关枚举值。

struct bar : foo<bar, foo_type::bar> { /* ... */ };
//               \_/  \___________/
//                ^ Type         ^ Value
理想情况下,这应该是在 foo 的第一个模板参数之间自动注册双向映射。 ,一个类型,第二个,一个值,只有继承语法和正确的模板参数,以便我以后可以做下面例子中的内容。
foo_type value = to_value<bar>; // Should be foo_type::bar
using type = to_type<foo_type::bar>; // Should be bar
我知道我可以为每个类型值对手动编写两个模板特化来做到这一点,但我想知道它是否会比不使用宏更乏味。
我已经尝试过的是......
  • 专门化模板别名以编写更少的代码来生成专门化。在当前的 C++ 版本 (17/20) 中显然不可能。
  • 专门化继承的模板成员类型。

  • struct foo_base
    {
        template<typename T>
        struct to_value
        {};
    
        template<foo_type E>
        struct to_type
        {};
    };
    
    template<typename T, foo_type E>
    struct foo : public foo_base
    {
        template<>
        struct to_value<T>
        {
            static constexpr auto value = E;
        };
    
        template<>
        struct to_type<E>
        {
            using type = T;
        };
    };
    
    然后它将与我在开始时介绍的内容类似地使用。
    foo_type value = foo_base::to_value<bar>::value; // Should be foo_type::bar
    using type = foo_base::to_type<foo_type::bar>::type; // Should be bar
    
    但它在 MSVC 上失败并出现以下错误。

    explicit specialization; 'foo_base::to_value' has already been instantiated

    'foo_base::to_value': cannot specialize template in current scope


    我觉得如果没有明确的手动特化,它可能无法实现,但是 C++17 允许许多令人惊讶的基于模板的 hack,所以在我放弃这个想法之前想与更有经验的人确认。

    最佳答案

    @HolyBlackCat 的回答太棒了。 Type-to-enum 可以通过比 ADL 黑客更简单的方式实现,所以我尝试将 enum-to-type 位提炼到最低限度:

    template <auto E>
    struct adl_to_type 
    {
        friend auto foo_type_to_type(adl_to_type);
    };
    
    template<typename T, foo_type E>
    struct foo 
    {
        friend auto foo_type_to_type(adl_to_type<E>) { return (T*)nullptr; };
    };
    
    template <foo_type E>
    using to_type = std::remove_pointer_t<decltype(foo_type_to_type(adl_to_type<E>{}))>;
    
    int main() 
    {
        to_type<foo_type::bar>{}.say();
        return 0; 
    }
    

    Run on gcc.godbolt.org

    它仍然让我大吃一惊。 auto返回类型在这里绝对是至关重要的。甚至将其更改为 T*foo会产生编译错误。我也尝试摆脱 adl_to_type并使用 integral_constant相反,但似乎声明 foo_type_to_type因为用于解析 ADL 的类型中的 friend 函数是这里的关键。

    关于c++ - 简明双向静态1 :1 mapping of values and types,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62448834/

    相关文章:

    C++ 强制模板参数

    c++ - 当模板函数实例化失败时回退到备用函数

    c++ - 将 std::invoke_result_t 与通用 lambda 一起使用时出现硬错误

    Qt Creator clang 代码模型 "could not parse an included file"警告和派生模板类中的错误

    c++ - 如何将 C++ MySQL 连接器库链接到 Cmake?

    c++ - '_Unwind_Resume'的多个定义

    asp.net-mvc - ASP.NET MVC 2 - HTML.EditorFor() 和自定义 EditorTemplates

    C++ 17 : How to call a different constructor using if constexpr?

    c++ - C++名称查找在这里做什么? (& GCC 对吗?)

    数组的c++类构造函数