代码之家  ›  专栏  ›  技术社区  ›  PatrykB

使用元编程选择int类型会产生错误

  •  0
  • PatrykB  · 技术社区  · 8 年前

    假设我有一个整数数组,随着时间的推移,它可能会变大。为了节省一些内存,我构造了一个类,该类接受将存储在数组中的最大值,并将其转换为以下整数类型之一: uint8_t uint16_t , uint32_t uint64_t .

    代码:

    #include <limits>
    #include <cstdint>
    
    template <uint64_t MAX_VAL>
    class SELECTOR_INT
    {
    private:
    
        using  enum_type = uint64_t;
    
        static enum : enum_type { success_8 =  1, success_16 =  2, success_32 =  3, success_64 =  4 };
        static enum : enum_type { failure_8 = 11, failure_16 = 12, failure_32 = 13, failure_64 = 14 };
    
        #define TYPE_MAX(_TYPE) static_cast<enum_type>(std::numeric_limits<_TYPE>::max())
        static enum : enum_type { result_8  = (                                   (MAX_VAL <= TYPE_MAX(uint8_t )) ) ? success_8  : failure_8  };
        static enum : enum_type { result_16 = ( (MAX_VAL > TYPE_MAX(uint8_t )) && (MAX_VAL <= TYPE_MAX(uint16_t)) ) ? success_16 : failure_16 };
        static enum : enum_type { result_32 = ( (MAX_VAL > TYPE_MAX(uint16_t)) && (MAX_VAL <= TYPE_MAX(uint32_t)) ) ? success_32 : failure_32 };
        static enum : enum_type { result_64 = ( (MAX_VAL > TYPE_MAX(uint32_t))                                    ) ? success_64 : failure_64 };
        #undef TYPE_MAX
    
        #define MIN(_LOP, _ROP) ((_LOP < _ROP) ? _LOP : _ROP)
        static enum : enum_type { RESULT = MIN(result_8, MIN(result_16, MIN(result_32, MIN(result_32, result_64)))) };
        #undef MIN
    
    private:
    
        template <enum_type num>
        struct CHOOSED;
    
        template <> struct CHOOSED <success_8 > { using TYPE = typename uint8_t;  };   // Line 162
        template <> struct CHOOSED <success_16> { using TYPE = typename uint16_t; };   // Line 163
        template <> struct CHOOSED <success_32> { using TYPE = typename uint32_t; };   // Line 164
        template <> struct CHOOSED <success_64> { using TYPE = typename uint64_t; };   // Line 165
    
    public:
    
        using TYPE = CHOOSED<RESULT>::TYPE;
    
    };
    
    using int_type = SELECTOR_INT<200>::TYPE;
    
    int main()
    {
        int_type test_variable = 0;
        return 0;
    }
    

    不幸的是,我把事情搞砸了,因为我遇到了以下错误:

    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(163): error C2766: explicit specialization; 'SELECTOR_INT<MAX_VAL>::CHOOSED<>' has already been defined
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(162): note: see previous definition of 'CHOOSED<, ?? :: ?? :: ?? ::<unnamed-enum-success_8> >'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(171): note: see reference to class template instantiation 'SELECTOR_INT<MAX_VAL>' being compiled
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(164): error C2766: explicit specialization; 'SELECTOR_INT<MAX_VAL>::CHOOSED<>' has already been defined
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(162): note: see previous definition of 'CHOOSED<, ?? :: ?? :: ?? ::<unnamed-enum-success_8> >'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(165): error C2766: explicit specialization; 'SELECTOR_INT<MAX_VAL>::CHOOSED<>' has already been defined
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(162): note: see previous definition of 'CHOOSED<, ?? :: ?? :: ?? ::<unnamed-enum-success_8> >'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(169): error C2027: use of undefined type 'SELECTOR_INT<4>::CHOOSED<0>'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(169): note: see declaration of 'SELECTOR_INT<4>::CHOOSED<0>'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(187): note: see reference to class template instantiation 'SELECTOR_INT<4>' being compiled
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(169): error C2061: syntax error: identifier 'TYPE'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(169): error C2238: unexpected token(s) preceding ';'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(187): error C2039: 'TYPE': is not a member of 'SELECTOR_INT<4>'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(187): note: see declaration of 'SELECTOR_INT<4>'
    
    1>D:/Dev/visual_studio/nevada_test_site/source/workspace/internship/hamiltonian/start.cu(187): error C2061: syntax error: identifier 'TYPE'
    

    我怎样才能解决这个问题?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Yakk - Adam Nevraumont    8 年前

    你的代码有很多问题。错误的标识符,试图专门化内部类,等等,并且可能在逻辑中出错。

    template<std::size_t I>
    struct index {
      static constexpr std::size_t value=I;
      constexpr operator std::size_t()const{return I;}
      constexpr index(){}
    };
    

    这只会使下面的内容更简单。

    first_ 获取一系列布尔值,并告诉您哪一个是第一个真布尔值:

    template<bool...>
    struct first_ {};
    template<bool... bs>
    struct first_<true, bs...>:index<0>{};
    template<bool... bs>
    struct first_<false, bs...>:index<first_<bs...>::value+1>{};
    

    nth

    template<std::size_t N, class...Ts>
    struct nth_impl{};
    template<class T0, class...Ts>
    struct nth_impl<0, T0,Ts...>{using type=T0;};
    template<std::size_t N, class T0, class...Ts>
    struct nth_impl<N, T0,Ts...>:nth_impl<N-1,Ts...>{};
    template<std::size_t N, class...Ts>
    using nth=typename nth_impl<N,Ts...>::type;
    

    然后,我们以一般方式解决问题:

    template<class T, T x, class...Ts>
    using smallest_that_fits = nth< first_<(x<=std::numeric_limits<Ts>::max())...>::value, Ts... >;
    

    最后,我们解决您的具体子问题:

    template<std::int64_t x>
    using choice = smallest_that_fits<
      std::int64_t, x,
      std::int8_t, std::int16_t, std::int32_t, std::int64_t
    >;
    

    你可以写 第n个 std::tuple 如果你愿意的话。和 index 可以是的别名 std::integral_constant<std::size_t .

    第一个_ _