我现在有一个模板,该模板从要存储的参数位数中推导出具体类型:

template<unsigned char BITS>
struct Register {
    using type = unsigned long;
};

template<>
struct Register<0> {
    using type = void;
};

template<>
struct Register<8> {
    using type = unsigned char;
};

template<>
struct Register<16> {
    using type = unsigned short;
};

template<>
struct Register<32> {
    using type = unsigned long;
};

有可能以某种方式扩展该模板,使其对于给定的位数自动推断出下一个更高特化的类型吗?
这意味着:
  • 寄存器产生特化寄存器
  • 寄存器实际上使用寄存器和
  • 寄存器导致寄存器。

  • 我想到过像Register这样的解决方案,可以推导出Register类型。但是我不确定这是否是正确的方法。

    但是,对于所有> = 33的值,应推断出类型为void或寄存器。

    例:
    Register<4>::type value;  // Register<8> will be used
    Register<33>::type value = 1; // Compile error -> type is void
    

    这可行吗?

    最佳答案

    首先,您需要引入定义递归的基本模板:

    template< int N > struct impl_Int
    {
        using type = impl_Int<N+1>::type;
    };
    

    接下来,为固定尺寸定义特化:
    const int impl_CHAR = sizeof(signed char) != sizeof(short)
        ? sizeof(signed char) * CHAR_BIT
        : INT_MIN;
    template<> struct Register<impl_CHAR>
    {
        using type = char;
    };
    
    const int impl_SHORT = sizeof(short) != sizeof(int)
        ? sizeof(short) * CHAR_BIT
        : INT_MIN + 1;
    template<> struct Register<impl_SHORT>
    {
        using type = short;
    };
    
    const int impl_INT = sizeof(int) != sizeof(long)
        ? sizeof(int) * CHAR_BIT
        : INT_MIN + 2;
    template<> struct Register<impl_INT>
    {
        using type = int;
    };
    
    const int impl_LONG = sizeof(long) * CHAR_BIT;
    template<> struct Register<impl_LONG>
    {
       using type = long;
    };
    

    最后,定义终止特化:
    template<> struct Register<INT_MAX>
    {
        using type = void;
    };
    

    有关实时示例,请参见here

    对于生产实现,您可能会将这些常量值隐藏在impl命名空间中,然后编写:
    template <int N>
    using Register = impl::Register<N>;
    

    还要注意,您可以通过使用C++ 11 fixed width integers并对其大小进行硬编码来简化此操作。这将消除对常量的需要:
    #include <climits>
    #include <cstdint>
    
    template< int N > struct Register
    {
        using type = typename Register<N+1>::type;
    };
    
    template<> struct Register<8>
    {
        using type = std::int8_t;
    };
    
    template<> struct Register<16>
    {
        using type = std::int16_t;
    };
    
    template<> struct Register<32>
    {
        using type = std::int32_t;
    };
    
    template<> struct Register<64>
    {
        using type = void;
    };
    
    int main() {
        using T1 = Register<3>::type;
        using T2 = Register<35>::type;
        T1 v1;
        T2 v2; // This line fails to compile: T2 is void.
    }
    

    Live example

    关于c++ - 递归推导缺少模板特化的值类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36793334/

    10-11 22:38
    查看更多