Physical Boost.Units Пользовательские литералы - PullRequest
6 голосов
/ 13 февраля 2012

Теперь, когда у нас скоро появятся пользовательские литералы (UDL), например, в GCC 4.7, я с нетерпением жду (физических) библиотек модулей (таких как Boost.Units ), использующих их для облегчения выражениятаких литералов, как 1+3i, 3m, 3meter или 13_meter.Кто-нибудь написал расширение для Boost.Units с использованием UDL, поддерживающего это поведение?

Ответы [ 2 ]

4 голосов
/ 14 февраля 2012

Никто не вышел с таким расширением. Только gcc (и, возможно, IBM?) Имеет UDL, так что это может быть какое-то время. Я надеюсь, что какие-то юниты превратятся в tr2, который начинается примерно сейчас. Если это произойдет, я уверен, что UDL для юнитов появится.

Это работает:

//  ./bin/bin/g++ -std=c++0x -o units4 units4.cpp

#include <boost/units/unit.hpp>
#include <boost/units/quantity.hpp>
#include <boost/units/systems/si.hpp>

using namespace boost::units;
using namespace boost::units::si;

quantity<length, long double>
operator"" _m(long double x)
{ return x * meters; }

quantity<si::time, long double>
operator"" _s(long double x)
{ return x * seconds; }

int
main()
{
  auto l = 66.6_m;
  auto v = 2.5_m / 6.6_s;
  std::cout << "l = " << l << std::endl;
  std::cout << "v = " << v << std::endl;
}

Я думаю, было бы не сложно пройтись по любимым юнитам и сделать это.

По поводу помещения их в библиотеку: Литеральные операторы являются функциями области имен. Конкуренция за суффиксы будет ужасной. Я бы (если бы меня повысили) получил бы

namespace literals
{
...
}

Тогда пользователи Boost могут сделать

using boost::units::literals;

вместе со всеми другими, использующими decls, которые вы обычно используете. Тогда вы не будете забиты, например, std::tr2::units. Точно так же, если вы катите свой собственный.

3 голосов
/ 18 декабря 2013

На мой взгляд, использование литералов для Boost.Units не слишком выгодно, поскольку при существующих возможностях все еще можно добиться более мощного синтаксиса.

В простых случаях, похоже, что литералы - это путь, но вскоре вы видите, что он не очень мощный.Например, вам все еще нужно определить литералы для объединенных единиц, например, как вы выражаете 1 м / с (один метр в секунду)?

В настоящее время:

auto v = 1*si::meter/si::second; // yes, it is long

, но слитералы?

// fake code
using namespace boost::units::literals;
auto v = 1._m_over_s; // or 1._m/si::second; or 1._m/1_s // even worst

Лучшее решение может быть достигнуто с помощью существующих функций.И вот что я делаю:

namespace boost{namespace units{namespace si{ //excuse me!
namespace abbreviations{
    static const length             m   = si::meter;
    static const time               s   = si::second;

    // ...
}
}}} // thank you!

using namespace si::abbreviations;
auto v = 1.*m/s;

Таким же образом вы можете сделать: auto a = 1.*m/pow<2>(s); или расширить аббревиатуры, если хотите (например, static const area m2 = pow<2>(si::meter);)

Что еще кроме этого вы хотите?

Может быть, комбинированное решение может быть способом

auto v = 1._m/s; // _m is literal, /s is from si::abbreviation combined with operator/

, но будет так много избыточного кода, и усиление будет минимальным(замените * на _ после числа.)

Один из недостатков моего решения состоит в том, что оно расширяет пространство имен общими однобуквенными именами.Но я не вижу выхода из этого, кроме как добавить подчеркивание (в начало или конец аббревиатуры), как в 1.*m_/s_, но, по крайней мере, я могу построить выражения реальных единиц.

...