使用元编程选择 int 类型,将生成错误

selecting int type with meta-programming, generates an error

本文关键字:错误 类型 int 编程 选择      更新时间:2023-10-16

假设我有一个整数数组,随着时间的推移可能会变大。为了节省一些内存,我构造了一个类,该类获取将存储在数组中的最大值,并将其转换为以下整数类型之一:uint8_tuint16_tuint32_tuint64_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'

问题:

我该如何解决这个问题?

你的代码有很多问题。 错误的标识符,试图专门化内部类等。 也许逻辑上有问题。

无论如何,我不喜欢这种方法;它涉及幻数和宏,一团糟。 只需直接解决问题:

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采用索引和类型序列,并返回第 n 个类型:

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
>;

如果您愿意,可以使用std::tuple编写nthindex可以是std::integral_constant<std::size_t的别名。

first_有一个尾随_否则我的编译器会在编译器错误中爆炸。