C++ C++;:在编译时确定给定整数类型的整数转换秩?

C++ C++;:在编译时确定给定整数类型的整数转换秩?,c++,c++11,C++,C++11,在我正在从事的一个项目中,我有一个数据结构,可以存储各种类型的数字,并且需要保证不会意外丢失精度/信息 因为标准C++允许一些有损的转换隐式发生,所以我使用了一种类型的特性,用它来确定我允许的转换,并禁止使用sFIFA.的那些不喜欢的类型。 我意识到在我如何做这件事的过程中有一个微妙的问题 下面是一段代码摘录: // If it is between two floating point types, no truncation is allowed. template <typename

在我正在从事的一个项目中,我有一个数据结构,可以存储各种类型的数字,并且需要保证不会意外丢失精度/信息

因为标准C++允许一些有损的转换隐式发生,所以我使用了一种类型的特性,用它来确定我允许的转换,并禁止使用sFIFA.

的那些不喜欢的类型。 我意识到在我如何做这件事的过程中有一个微妙的问题

下面是一段代码摘录:

// If it is between two floating point types, no truncation is allowed.
template <typename A, typename B>
struct safe_numeric<A,
                    B,
                    typename std::enable_if<(std::is_floating_point<A>::value &&
                                             std::is_floating_point<B>::value)>::type> {
  static constexpr bool value = sizeof(A) >= sizeof(B);
};
并使用该元函数而不是
sizeof

如果我想对整型做这个。。。还有很多

还有一个问题是不需要存在整数类型,因此我可能希望尝试检测该场景,以便编译
转换\u rank
模板

是否有更好的/标准的方法来实现这一点?我在标准库中没有找到“conversion_rank”元函数,我猜标准实际上没有给出数值,它只是指定了“higher”和“lower”。但也许在
boost
/其他一些策略中有一些东西不那么费力,也不依赖于
sizeof

我最终使用的开源策略

我用来建立等级的代码如下(请参阅):

枚举类数值类:字符{整数,字符,宽字符,布尔,浮点};
模板
结构分类;
模板
结构分类{
静态constexpr numeric_class value=numeric_class::integer;
};
#定义分类(T,C)\
模板\
结构分类_数值{\
静态constexpr numeric_class value=numeric_class::C\
}
分类(字符、字符);
分类(有符号字符、字符);
分类(无符号字符、字符);
分类(字符,字符);
分类(字符,字符);
分类(wchar\u t,宽字符);
分类(布尔,布尔);
分类(浮动、浮动);
分类(双重、浮动);
分类(长双、浮动);
#未定义分类
模板
结构秩_数值;
#定义秩(T,V)\
模板\
结构秩_数值{\
静态constexpr int value=V\
}
#定义铀(T,V)\
秩(T,V)\
秩(无符号T,V)
秩(bool,0);
秩(符号字符,-1);
铀(半焦,0);
等级(第16章,第1节);
排名(第32位,第2位);
乌兰克(短,1);
乌兰克(国际,2);
乌兰克(长,3);
乌兰克(长,长,4);
等级(浮动,0);
职级(双,1);
排名(长双,2);
#未定义秩

既然你本质上想阻止缩小,那就看看
Dest{std::declval()}
?这正是我所希望的答案,谢谢!事实上,我收回这句话。如果你想要完全的可移植性,你必须用等级来写这个
{}
将允许LP64上的
long long
long
。@T.C.
long long
long
转换是标准中允许的,还是编译器中的一个错误?我很确定给定两个整数类型
T1
T2
,大小相同,但转换等级低于
int
,使用通常的TMP技术,如果不对它们进行硬编码,就不可能确定哪一个具有更高的等级。因此,如果你想要100%的可移植性,你要么自己做硬编码,要么找人帮你做:)
template <typename T>
struct conversion_rank;

template <>
struct conversion_rank<float> {
  static constexpr std::size_t value = 0;
};

template <>
struct conversion_rank<double> {
  static constexpr std::size_t value = 1;
};

template <>
struct conversion_rank<long double> {
  static constexpr std::size_t value = 2;
};
enum class numeric_class : char { integer, character, wide_char, boolean, floating };

template <typename T, typename ENABLE = void>
struct classify_numeric;

template <typename T>
struct classify_numeric<T, typename std::enable_if<std::is_integral<T>::value>::type> {
  static constexpr numeric_class value = numeric_class::integer;
};

#define CLASSIFY(T, C)                                                                             \
  template <>                                                                                      \
  struct classify_numeric<T, void> {                                                               \
    static constexpr numeric_class value = numeric_class::C;                                       \
  }

CLASSIFY(char, character);
CLASSIFY(signed char, character);
CLASSIFY(unsigned char, character);
CLASSIFY(char16_t, character);
CLASSIFY(char32_t, character);
CLASSIFY(wchar_t, wide_char);
CLASSIFY(bool, boolean);
CLASSIFY(float, floating);
CLASSIFY(double, floating);
CLASSIFY(long double, floating);

#undef CLASSIFY

template <typename T>
struct rank_numeric;

#define RANK(T, V)                                                                                 \
  template <>                                                                                      \
  struct rank_numeric<T> {                                                                         \
    static constexpr int value = V;                                                                \
  }

#define URANK(T, V)                                                                                \
  RANK(T, V);                                                                                      \
  RANK(unsigned T, V)

RANK(bool, 0);

RANK(signed char, -1);
URANK(char, 0);
RANK(char16_t, 1);
RANK(char32_t, 2);

URANK(short, 1);
URANK(int, 2);
URANK(long, 3);
URANK(long long, 4);

RANK(float, 0);
RANK(double, 1);
RANK(long double, 2);

#undef RANK