加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C:在编译时确定给定积分类型的积分转换等级?

发布时间:2020-12-16 06:52:05 所属栏目:百科 来源:网络整理
导读:在我正在开发的项目中,我有一个数据结构,可以存储各种类型的数据,并且需要保证不会意外丢失精度/信息. 因为标准C允许隐式发生一些有损转换,所以我制作了一个类型特征,用于确定我允许的转换次数,并禁止使用SFINAE的转换. 我意识到我在做这件事时有一个微妙的
在我正在开发的项目中,我有一个数据结构,可以存储各种类型的数据,并且需要保证不会意外丢失精度/信息.

因为标准C允许隐式发生一些有损转换,所以我制作了一个类型特征,用于确定我允许的转换次数,并禁止使用SFINAE的转换.

我意识到我在做这件事时有一个微妙的问题.

这是一段代码摘录:

// 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);
};

意图是,float可以提升为double或long double,而double可以提升为long double,但它不能变小.

但是,在这里使用sizeof是不好的,因为在sizeof(double)== sizeof(float)的机器上,根据此模板将double转换为float是合法的.这将使我的程序不可移植 – 开发人员可以编写在其机器上编译和工作的代码,并且事实上,不会失去精度.但在其他一些机器上,可能只是无法编译并抱怨不安全的转换.

我真正想要的是获得转换等级,例如[4.13] [conv.rank]中的标准所描述的.我想为浮点和整数类型执行此操作.

例如,我可以自己动手:

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

并使用该元函数而不是sizeof.

如果我想为整数类型做这个…还有更多它们.

还有一个问题是不需要存在整数类型,所以我可能想尝试检测那个场景,以便convert_rank模板可以编译.

有没有更好/标准的方法来解决这个问题?我没有在标准库中找到“conversion_rank”元函数,我想标准实际上并没有给出数值,它只是指定“更高”和“更低”.但也许有一些东西在推动/其他一些策略中不那么费力并且不依赖于sizeof?

解决方法

我开源 the component,我最终用于此.

我用来制作排名的代码是这样的(见here):

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读