Это действительно минималистский пример. я использую 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)
было бы решением, но я все еще чувствую, что мне чего-то не хватает в том, что компилятор не может автоматически преобразовать скаляр в нужный тип.
Заранее большое спасибо!
шаблонные функции отличаются от шаблонных функций. Компилятор решает выбрать шаблонную функцию без учета неявного приведения / продвижения. Это просто искать точное соответствие.
Вот как 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
который будет происходить почти полностью от повышения — но определим умножение по-другому, предложенным мной.
Просто решите, с чем вам легче идти
L
— 0.5L
сделать длинную двойную константу) Других решений пока нет …