Comments (6)
This is more input/output (io) than and serialization. This is not implemented probably because it requires a pretty complicated parser of units and the result can be error prone. For example, in the most flexible cases requires numeric/unit conversions. It is not clear if inconsistent input out would allowed and the gain is marginal after a lot of work and a lot of assumptions.
Having said that, Boost.Serialization supports serialization and deserialization of Boost.Units but not for human consumption.
from units.
I'm not really talking about parsing, for example, "10 m" into a feet quantity, but at least having the simple case of allowing parsing "10 m" into a meter quantity.
Shouldn't it be only a matter of checking the prefix, and parsing the numeric value ?
from units.
I'm not really talking about parsing, for example, "10 m" into a feet quantity, but at least having the simple case of allowing parsing "10 m" into a meter quantity.
Shouldn't it be only a matter of checking the prefix, and parsing the numeric value ?
Not really, there are a lot of variables that can spoil the apparent simplicity. For example the format of the output depends on the files that are included for example
std::cout << 3.14*si::joule << std::endl
outputs "3.14 m^2 kg s^-2". but if you #include<boost/units/systems/si/io.hpp>
it will output 3.14 J
. So which of the two should be checked against? not to mention other surprising behavoir relative to scaled quantities (for example an input with 3.14e6 ยตJ
).
I would say that in the best imaginable case human input will always give surprising results, the main problem is that the parser will have to have a lot of compile time information about all possible ways to interpret and disambiguate unit initials, etc.
Having said that, yes you can in principle be very strict and only accept input that exactly matches the output, at least for the unit portion. Again, with the caveat that many configuration variables can affect the output format. But if you promise the input and output will occur with the same compilation configuation perhaps you can accept this implementation below.
This solves your problem the way you want but it also shows the exceeding number of assumptions made but this simple parser. This is not at the quality or generality level expected for a library like Boost.Units, so it is probably a good thing that they decided to leave input from streams unimplemented.
namespace boost{
namespace units{ // I am stomping over boost.units namespace for simplicity
template<class U, class T>
std::istream& operator>>(std::istream& is, quantity<U, T>& q){
typename quantity<U, T>::value_type val; is >> val;
std::string const expected = to_string(U{});
std::string tag(expected.size()+1, 0); is.get(&tag[0], tag.size()+1);
if(tag[0]==' ' and tag.substr(1)==expected){
q = quantity<U, T>::from_value(val);
}else{
// std::cerr<<"error expected "<< expected <<", got "<< tag <<std::endl;
is.setstate(std::ios::failbit);
}
return is;
}
}}
int main(){
{
quantity<si::length> l = 3.14*si::meter;
std::stringstream ss; ss << l << "abc" << std::endl;
quantity<si::length> l2; ss >> l2;
assert(ss and l == l2);
std::string check; ss >> check; assert(check=="abc");
}
{
quantity<si::energy> e = 5.24*si::joule;
std::stringstream ss; ss << e << "abc" << std::endl;
// promise not do funny stuff between write and read, like including new units/io headers
quantity<si::energy> e2; ss >> e2;
assert(ss and e == e2);
std::string check; ss >> check; assert(check=="abc");
}
}
from units.
This reminded me that I have some code that I did not update to the gitlab repository with my custom extensions to boost.units. The code I presented above is now here:
https://gitlab.com/correaa/boost-units/blob/master/io/input.hpp
This also includes another feature which I think is more sane than general input, which it to leave the user to generate dimensionless expressions in which the normal input can be performed.
For example,
suppose you know a certain input ("5") is in micro meters. Then you get the variable in meters.
quantity<si::length> l; in >> l/(si::micro*si::meter); assert( l == 5e-6*si::meter );
So as long as you can generate a dimensionless expression (ok, by division only for the moment) then this will work. I think this is better than investing in a general input parser for a lot of work that is going be thrown away since the compile time type cannot be changed anyway.
from units.
Thank you for the code and these complete answers, this should do the trick.
If I were to give my two cents, I would say that the way IO is handled by the library is either too complicated or too "sneaky". Just including a header shouldn't, imho, change the results of an operation. If it's just to change the way units output themselves, wouldn't it be just fine, for example, to create new stream flags ?
I agree with you that maybe, handling dimensionless quantities are more sane, as IO should be well documented and as clear as possible.
from units.
from units.
Related Issues (16)
- subtraction of dimensionless quantities produce surprising result HOT 2
- Gauss system support HOT 1
- Unit conversion ignores offsets. HOT 2
- is_constructible has unexpected results HOT 2
- one/quantity support HOT 2
- Improve documentation
- [Feature Request]: unit_cast
- Please merge the 'develop' branch change into 'master' for the Boost 1.75 release
- Provide interoperability between std::chrono::duration and boost::units::quantity<time> HOT 1
- Degree definition causes quite big conversion error between degrees and radians.
- Forward declarations for boost units
- fma in boost/units/cmath.hpp?
- noexcept support
- boost::units::quantity should be trivial HOT 18
- Explicit construction of quantities using units that are not defined in system compiles but mathematically fails
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from units.