如何将来自用户定义文字的可变char模板参数转换回数字类型

How can variadic char template arguments from user defined literals be converted back into numeric types?

本文关键字:char 参数 转换 类型 数字 将来 何将来 文字 定义 用户      更新时间:2023-10-16

这个问题是因为这个

c++ 11允许您为数字字面值定义如下的字面值:

template<char...> OutputType operator "" _suffix();

意味着503_suffix会变成<'5','0','3'>

这很好,尽管在它的形式中不是很有用。

如何将其转换回数字类型?这将把<'5','0','3'>变成constexpr 503。此外,它还必须处理浮点量。<'5','.','3>会变成int 5float 5.3

在上一个问题中找到了部分解决方案,但它不适用于非整数:

template <typename t>
constexpr t pow(t base, int exp) {
  return (exp > 0) ? base * pow(base, exp-1) : 1;
};
template <char...> struct literal;
template <> struct literal<> {
  static const unsigned int to_int = 0;
};
template <char c, char ...cv> struct literal<c, cv...> {
  static const unsigned int to_int = (c - '0') * pow(10, sizeof...(cv)) + literal<cv...>::to_int;
};
// use: literal<...>::to_int
// literal<'1','.','5'>::to_int doesn't work
// literal<'1','.','5'>::to_float not implemented

总有简单的方法。非类型形参包可以按如下方式展开为初始化列表:

#include <iostream>
template<char... Chars>
  double
  operator "" _suffix()
  {
    const char str[]{Chars..., ''};
    return atof(str);
  }
int
main()
{
  std::cout << 123.456789_suffix << std::endl;
}

我认为以下应该在没有指数部分(未经测试)的浮点数上工作:

template<bool fp, long long num, long long denom, char ...> struct literal;
template<bool fp, long long num, long long denom> struct literal<fp, num, denom>
{
   static constexpr double value() { return (1.0*num)/denom; }
};
template<long long num, long long denom, char digit, char... rest>
  struct literal<false, num, denom, digit, rest...>
{
  static constexpr double value()
  {
    return literal<false, 10*num + (digit-'0'), denom, rest...>::value();
  }
};
template<long long num, long long denom, char digit, char... rest>
  struct literal<true, num, denom, digit, rest...>
{
  static constexpr double value()
  {
    return literal<true, 10*num + (digit-'0'), 10*denom, rest...>::value();
  }
};
template<long long num, long long denom, char... rest>
  struct literal<false, num, denom, '.', rest...>
{
  static constexpr double value()
  {
    return literal<true, num, denom, rest...>::value();
  }
};
template<char... c> double operator "" _dbl()
{
  return literal<false, 0, 1, c...>::value();
}

如何将其推广到指数部分应该是显而易见的。

当然还需要做一些错误检查(确保字符确实是数字)。