GithubHelp home page GithubHelp logo

Comments (8)

Morwenn avatar Morwenn commented on August 15, 2024 1

You could look at Howard Hinnant's date library. IIRC there's a IO part that handles µs smoothly for microseconds. He may have used an elegant and portable solution.

from units.

vlad-ivanov-name avatar vlad-ivanov-name commented on August 15, 2024 1

I'd like to note that having a way of extracting units without std::ostream would be nice for embedded applications. The regex solution is even less applicable there.

from units.

nholthaus avatar nholthaus commented on August 15, 2024

First, let's solve your problem at hand. Then I'll provide some explanation of why those things are the way they are.

The easiest way to do want you want is to write a small function to parse the stream output of a unit value:

#include <sstream>
#include <regex>
#include <tuple>

template<typename T>
std::tuple<std::string, std::string> parseUnit(T val)
{
	static_assert(units::traits::is_unit_t<T>::value, "val must be a unit_t type.");
	static std::regex unitRegex(R"((.*)\s+(.*))");
	
	std::stringstream ss;
	std::string s;
	std::smatch matches;

	ss << val;
	s = ss.str();
	if (std::regex_match(s, matches, unitRegex))
	{
		if (matches.size() == 3)
		{
            // to be extra fancy, replace "deg" in matches[2] (if found) with "°"
			return std::make_tuple(matches[1], matches[2]);
		}
	}

	return std::make_tuple("", "");
}

and then usage would be like so:

int main()
{
	millimeter_t myDist(42);
	auto unitTuple = parseUnit(myDist);

	std::string val, abbreviation;
	std::tie(val, abbreviation) = unitTuple;

	if(val == "42")
                std::cout << "value is correct" << std::endl;
	if(abbreviation == "mm")
                std::cout << "abbreviation is correct" << std::endl;
}

Why not just access the abbreviation directly?

One of the benefits of a compile time unit library like this is that, well, all the work is done at compile time. This means that in terms of storage and efficiency, using units has the same cost of using double values. Which means that the abbreviation isn't ever actually instantiated or stored anywhere, so it can't be accessed in any type of direct way.

The only thing that actually knows the string abbreviation is the unit's overloaded operator<<, so the easiest way to get the abbreviation back out is to << the unit into a stringstream and parse it with a very simple regular expression. Hard ways could include having some type of tag dispatch function or wrapping the ADD_UNIT macro with something that saves the abbreviation for you.

The above parse function should be fine for most applications.

Why not use UTF-8?

The technical answer is that the unit literals are made from the unit abbreviation, and literals are limited to an underscore followed by a lower-case letter in c++11, and an underscore followed by a letter in c++14. I couldn't even make _% work as a literal (which made me sad).

Could we split the literal abbreviation from the string abbreviation? Yeah, with some additional complexity. However, as a library author, I can't really force your project settings to support UTF-8, and I would get a bunch of "units print gibberish" issues. While I certainly agree it's sub-optimal, "degC" and least prints for everyone and is relatively understandable.

Would I pull something that split the literal/printed abbreviations if it handled different text encoding incredibly gracefully? You bet!

from units.

nholthaus avatar nholthaus commented on August 15, 2024

@Morwenn I'll take a look.

from units.

tonypilz avatar tonypilz commented on August 15, 2024

The library uses ascii character 181 for µ (see line 6937 ff).

from units.

nholthaus avatar nholthaus commented on August 15, 2024

with c++17 you could do that easily enough for your most common unit types using if constexpr(). There's not much to be done on the library side as the abbreviation isn't actually stored anywhere (to maintain equivalent performance to double), so there's no way to access it outside of that one macro.

from units.

vlad-ivanov-name avatar vlad-ivanov-name commented on August 15, 2024

Right, constexpr if could certainly help. I was also thinking maybe having a member function returning char const *:

    constexpr char const * t() {
        return "asd";
    }

Would that affect performance?

from units.

nholthaus avatar nholthaus commented on August 15, 2024

In v2.3 there is a to_string overload that will do the following:

auto a = 3.5_m;
auto str = units::length::to_string(a);
std::cout << str;  // prints "3.5 m"

also abbreviation which does:

auto a = 3.5_m;
auto str = units::length::abbreviation(a);
std::cout << str;  // prints "m"

to keep compile-time down, these are defined for each unit in the unit category namespace. It's only going to work for library defined units. Hopefully works for most use cases.

from units.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.