Как можно преобразовать аргументы шаблона переменной из определяемых пользователем литералов обратно в числовые типы? - PullRequest
4 голосов
/ 13 ноября 2011

Этот вопрос задается из-за этого .

C ++ 11 позволяет определять литералы, подобные этому, для числовых литералов:

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

Это означает, что 503_suffix станет <'5','0','3'>

Это хорошо, хотя и не очень полезно в той форме, в которой оно находится.

Как можноЯ преобразовываю это обратно в числовой тип? Это превратит <'5','0','3'> в constexpr 503.Кроме того, он также должен работать с литералами с плавающей точкой.<'5','.','3> превратится в int 5 или float 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

Ответы [ 2 ]

4 голосов
/ 13 ноября 2011

Там всегда легкий путь. Нетипичный пакет параметров может быть расширен в список инициализаторов следующим образом:

#include <iostream>

template<char... Chars>
  double
  operator "" _suffix()
  {
    const char str[]{Chars..., '\0'};
    return atof(str);
  }

int
main()
{
  std::cout << 123.456789_suffix << std::endl;
}
3 голосов
/ 13 ноября 2011

Я думаю, что следующее должно работать с плавающими без экспоненциальной части (не проверено):

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

Как расширить это, чтобы принять экспоненциальную часть, должно быть очевидно.

Конечно, одинтакже хотел бы выполнить некоторую проверку ошибок (убедитесь, что символы действительно являются цифрами).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...