-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strengthen unit aliases #150
Conversation
It's somewhat off-topic, but if you want to reduce symbols and template instantiations, a first easy step would be to replace the use of template<bool>
struct conditional
{
template<typename T, typename U>
using type = T;
};
template<>
struct conditional<false>
{
template<typename T, typename U>
using type = U;
};
template<bool B, typename T, typename U>
using conditional_t = typename conditional<B>::template type<T, U>; This implementation of conditional only produces template instantiations for |
I mean to reduce instantiations of types in this library, so no unnecessary work is done by design. I'd rather not reimplement |
e646b14
to
f25e433
Compare
I may have merged this badly... |
This is a mess of rebases and manual merging conflict resolutions of all my concurrent PRs. Don't worry about it. |
c7f7c4c
to
759b9b0
Compare
I have removed all unrelated commits. I'll now start trying out the macros. |
Seems like VS2017 and Clang 5 are chocking on the lack of viable constructors or deduction guides. My Clang 6, Travis's GCC 7 and my GCC 8 all compile fine and pass the tests. I'd guess that Clang 6 and GCC are correct. I'll see if adding some redundant deduction guides makes things work. |
I'd be OK w/ clang 6 and gcc 7 as minimum versions (seems fair for c++17), but would really like to continue to support VS 2017. |
|
yeah to keep the syntax consistent (and to be consistent w/ previous usage) I think it would be good to include the deduction guide. As a design goal, we shouldn't require template usage in end-user code for basic dimensional-analysis functionality. I'm going to play with this over the weekend so I can get a feel for the changes. Looks good overall. Did you notice whether it helped with the error messages or not? |
I have yet to check on the produced error messages. |
3fcac6b
to
680e4e7
Compare
I've rebased and cleaned up the commits. Seems like VS2015 didn't work with the deduction guide for the default constructor. Later, I hope to convert the length units from aliases to strong type aliases. Followed by all the other units. |
f3377ba
to
f389c9b
Compare
I'll revert renaming the units to reduce the scope of the PR. Strong typing will make #126 (comment) possible, which will also help simplify the logic of other things I want to propose. |
yeah, renaming should be a PR on its own. I've been meaning to solicit some input from you about that. It was part of my initial motivation for 3.0 but I'm wondering if we're making a useful change or breaking compatibility for no good reason. I'm kind of on the fence. |
VS2017's error seems to be SFINAE related. I hope I can decipher it. |
dcff619
to
029c700
Compare
Looks like the decibel units of integral underlying type are too error prone: units/unitTests/main.cpp:1577: Failure
Expected: ++b_dBW
Which is: 2 dBW
To be equal to: dBW_t(2)
Which is: 0 dBW
units/unitTests/main.cpp:1578: Failure
Expected: b_dBW++
Which is: 2 dBW
To be equal to: dBW_t(2)
Which is: 0 dBW
units/unitTests/main.cpp:1579: Failure
Expected: b_dBW
Which is: 3 dBW
To be equal to: dBW_t(3)
Which is: 0 dBW
units/unitTests/main.cpp:1580: Failure
Expected: +b_dBW
Which is: 3 dBW
To be equal to: dBW_t(3)
Which is: 0 dBW
units/unitTests/main.cpp:1581: Failure
Expected: b_dBW
Which is: 3 dBW
To be equal to: dBW_t(3)
Which is: 0 dBW
[ FAILED ] UnitContainer.unitTypeUnaryAddition (0 ms)
units/unitTests/main.cpp:1685: Failure
Expected: --b_dBW
Which is: 3 dBW
To be equal to: dBW_t(3)
Which is: 0 dBW
units/unitTests/main.cpp:1686: Failure
Expected: b_dBW--
Which is: 3 dBW
To be equal to: dBW_t(3)
Which is: 0 dBW
units/unitTests/main.cpp:1687: Failure
Expected: b_dBW
Which is: 2 dBW
To be equal to: dBW_t(2)
Which is: 0 dBW
units/unitTests/main.cpp:1688: Failure
Expected: -b_dBW
Which is: -2 dBW
To be equal to: dBW_t(-2)
Which is: 0 dBW
units/unitTests/main.cpp:1689: Failure
Expected: b_dBW
Which is: 2 dBW
To be equal to: dBW_t(2)
Which is: 0 dBW
[ FAILED ] UnitContainer.unitTypeUnarySubtraction (1 ms) |
/home/travis/build/nholthaus/units/unitTests/main.cpp:2476: Failure
Expected: "8 cu_ft"
To be equal to: output.c_str()
Which is: "0.226535 m^3" This test is failing because |
a1c9f76
to
33c84a8
Compare
Now I'm trying to solve #126 (comment) and 69bb2fb. |
Another thing that could help with the error messages is making the Then we could invest on making the unit manipulators result in strong type aliases themselves, like having I think this alternative, yet nonconflicting approach is worth investigating. Do you mind if I open a separate, possibly competing, PR for that? |
Yeah I think it's worthwhile. There was a point in the early 2.0's where
most of the (formerly named) units were still structs and we had error
messages similar to `units::unit<units::length::meter, int> `. They were
still very clear, even though they're more verbose than `units::length::meter_t<int>` (except for complex ephemeral units, which we don't need to worry
about so much since they're basically user defined and domain specific, or
intermediate). No one was really complaining about complex errors back then.
Am I wrong in saying that this approach is not only non-conflicting, but
actually complementary to the current PR? As far as I can tell, everything
we strengthen is a net win.
|
Yeah, they can also be complementary. |
That is, convert to the underlying type in the caller.
Modifies macros to allow arbitrary units. Also adds missing `UNIT_ADD_STRONG` for `dB_t`.
9da72c0
to
d92954e
Compare
Done. |
looks like the brackets for the default constructors are only necessary for |
Oh, of course. Thank you. |
Why a0bdbf5? They were supposed to test the default construction of |
Discussed in #138.
This is a hack to get a feeling of how it would be to make the units actual types and not aliases. This would allow us to use CTAD (which isn't looking hopeful for type aliases in C++20) and better error messages.
My observations:
std::common_type
andstd::hash
work require us to add more symbols (specializations) for each strong unit alias.std::is_same_v
forhas_equivalent_unit_conversion
.While working on this, I'll see if I can reduce the amount of symbols the library produces. Making
is_unit
whatis_derived_from_unit
(added in this hack) is and taking into account everywhere of this new definition should help there.Foreseeable future work includes preserving the strong unit alias whenever possible. As it is, it converts to its base ASAP, losing on the advantage of better error messages. And, of course, making the strong unit alises templated entities.
I just wanted to get this hack out. I'll make it a proper work later. As such, much of this message will be out-of-date and edited out.