как использовать тип примитива постоянной времени компиляции - PullRequest
0 голосов
/ 11 января 2019

Как использовать тип примитива постоянной времени компиляции в качестве объявления типа для других переменных?

Я пытаюсь сделать несколько шаблонов метапрограммирования в c ++ для преобразования единиц СИ. Все сводится к тому, как автоматически определить, какая точность примитивов мне нужна после одного оператора плюс. Например:

template<typename Precision>
class Unit {
public:
    Unit(Precision v) : value(v) {}
    Precision value;
};
template<typename Precision1, typename Precision2>
struct PrecisionTransform {
    constexpr static auto test = (Precision1)1 * (Precision2)1; // Compile time constant
    using Type = Precision1; // TODO: ideally typeof(test)
};
template<typename Precision1, typename Precision2>
Unit<PrecisionTransform<Precision1, Precision2>::Type> operator+(const Unit<Precision1>& x, const Unit<Precision2>& y)
{
    return Unit<PrecisionTransform<Precision1, Precision2>::Type>(x.value + y.value);
}

int main()
{
    Unit<double> a = 2.0;
    Unit<float> b = 1.0f;
    auto c = a + b;
    return 0;
}

или, проще говоря, может ли что-то подобное произойти?

float a = 1;
typeof(a) b = 2;

Это кажется вполне возможным, так как я зашел так далеко. Но я не уверен, как использовать

1 Ответ

0 голосов
/ 11 января 2019

Ты почти понял. Как уже указывалось max66, используйте decltype. Прежде всего, вы можете заменить свой класс PrecisionTransform псевдонимом следующего типа (для этого вам нужно #include <utility>):

template <typename Precision1, typename Precision2>
using TransformType = decltype(std::declval<Precision1>() * std::declval<Precision2>());

std::declval<XYZ>() - это просто более общий способ сказать (Precision1)1, который позволяет вам также использовать типы, у которых нет доступных конструкторов (в вашем случае это не имеет значения, поскольку вы используете только примитивы).

Ваш operator+ затем изменяется на:

template<typename Precision1, typename Precision2>
Unit<TransformType<Precision1, Precision2>> operator+(const Unit<Precision1>& x, const Unit<Precision2>& y)
{
    return Unit<TransformType<Precision1, Precision2>>(x.value + y.value);
}

Обратите внимание, что вы получили опечатку в вашей версии operator+ (оба операнда использовали Precision1).

Как вы можете видеть здесь , основные компиляторы согласны с этим.

...