Я смотрел на класс std::ratio<>
из стандарта C ++ 11, что позволяет сделать рациональную арифметику во время компиляции.
Я обнаружил, что дизайн шаблона и операции, реализованные с классами, слишком сложны, и не нашел никаких причин, по которым они не могли бы просто использовать более простой и интуитивный подход, реализуя действительно простой рациональный класс и определяя constexpr
функции для операторов. В результате класс стал бы проще в использовании, а преимущества времени компиляции остались бы.
Кто-нибудь имеет представление о преимуществах нынешнего std::ratio<>
дизайн по сравнению с простой реализацией класса с использованием constexpr
? На самом деле, я не могу найти преимущества для текущей реализации.
когда N2661 было предложено, ни один из авторов предложения не имел доступа к компилятору, который реализовал constexpr
, И никто из нас не был готов предложить что-то, что мы не могли построить и протестировать. Так что, можно ли сделать лучший дизайн с constexpr
не было даже частью рассмотрения для дизайна. Дизайн был основан только на тех инструментах, которые были доступны авторам в то время.
Решение constexpr решает совершенно другую проблему. std::ratio
был создан для использования в качестве моста между переменными, которые используют разные единицы, а не в качестве математического инструмента. В этих обстоятельствах вы абсолютно обязательно хотите, чтобы отношение было частью типа. Решение constexpr не будет работать там. Например, не удастся реализовать std::duration
без пространства времени выполнения и затрат времени выполнения, потому что каждый объект продолжительности должен был бы нести свою информацию о знаменателе / знаменателе в пределах объекта.
std::ratio
и окружающие его механизмы всегда будут работать во время компиляции благодаря метапрограммированию шаблонов и манипулированию типами. constexpr
требуется только для запуска во время выполнения, когда константное выражение требуется средствами C ++ (такими как параметры шаблона или инициализация constexpr
переменная).
Итак, что для вас важнее: выполнение во время компиляции или быть «более простым и интуитивно понятным»?
определение функций constexpr для оператора
Вы все еще можете сделать это поверх существующих std::ratio
:
#include <ratio>
// Variable template so that we have a value
template<
std::intmax_t Num,
std::intmax_t Denom = 1
>
auto ratio_ = std::ratio<Num, Denom>{};
// Repeat for all the operators
template<
std::intmax_t A,
std::intmax_t B,
std::intmax_t C,
std::intmax_t D
>
constexpr typename std::ratio_add<std::ratio<A, B>, std::ratio<C, D>>::type
operator+(std::ratio<A, B>, std::ratio<C, D>) {}
// Printing operator
template<
std::intmax_t A,
std::intmax_t B
>
std::ostream &operator<<(std::ostream &os, std::ratio<A, B> r) {
return os << decltype(r)::num << "/" << decltype(r)::den;
}
#include <iostream>int main() {
std::cout << ratio_<1,2> + ratio_<1,3> << std::endl;
return 0;
}
5/6