умножение скаляра на boost.units.quantity (проблемы с автоматическим преобразованием типов?)

Это действительно минималистский пример. я использую Boost.Units следующим образом:

#define REAL double
...
using namespace boost::units;
quantity<si::velocity, REAL> v;

тогда иногда мне нужно что-то вроде

quantity<si::velocity, REAL> v_halved;
v_halved = 0.5 * v;

Это работает нормально, потому что компилятор обрабатывает 0.5 как double, Но когда REAL что-то другое, то я получаю ошибку компиляции, например если бы я изменил определение REAL в long double компиляция жалуется:

error: no match for ‘operator*’ in ‘5.0e-1 * v’
/usr/include/boost/units/detail/one.hpp:58: note: candidates are: boost::units::one boost::units::operator*(const boost::units::one&, const boost::units::one&)

Глядя в Boost.Units документация Я основал, что operator* перегружается следующим образом:

// runtime scalar times quantity
template<typename Unit, typename X>
multiply_typeof_helper< X, quantity< Unit, X > >::type
operator*(const X & lhs, const quantity< Unit, X > & rhs);

Хотя из определения ясно, что скаляр и внутренний тип количества должны быть одинаковыми, я ожидаю, что компилятор автоматически преобразует тип, когда преобразование может быть выполнено неявно (например, из double в long double). Однако я думаю, что я могу что-то упустить, потому что автоматическое преобразование типов, безусловно, работает для других простых функций, таких как long double f(long double const & ld),

Моя проблема в том, что я использовал такие выражения, как v_halved = 0.5 * v довольно много, и мой проект уже стал значительно большим, и это только сейчас, после того, как нужно определить REAL как long double что я понимаю, что это проблема. Итак, мне было интересно об обходном пути / решении этого, я знаю, что static_cast<REAL>(0.5) было бы решением, но я все еще чувствую, что мне чего-то не хватает в том, что компилятор не может автоматически преобразовать скаляр в нужный тип.

Заранее большое спасибо!

3

Решение

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

Вот как C ++ работает в этой области.

Чтобы получить точное соответствие, вам понадобятся такие operator * определение (обратите внимание на этот дополнительный шаблонный параметр Y):

template<typename Unit, typename X, typename Y>
typename multiply_typeof_helper< X, quantity< Unit, X > >::type
inline operator*(const Y & lhs, const quantity< Unit, X > & rhs)
{
return static_cast<X>(lhs) * rhs;
}

но я боюсь что помешает повысить определение *, Вы можете играть с этим — как определить свой собственный quantity который будет происходить почти полностью от повышения — но определим умножение по-другому, предложенным мной.

Просто решите, с чем вам легче идти

  • делать статическое приведение (или лучше просто добавить L0.5L сделать длинную двойную константу)
  • или сделать несколько комбинаций с шаблонами.
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]