I am trying to defined a constexpr in terms of kilometers instead of meters using boost units. Everything I have read indicates that both lines below should work, but only the top line compiles for me in clang 10.
Here's a godbolt link for the lazy: https://godbolt.org/z/38je3z
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/prefixes.hpp>
#include <boost/units/unit.hpp>
class earthConstants{
public:
// Works
static constexpr boost::units::quantity<boost::units::si::length> earth_radius = (6371008.7714* boost::units::si::meters);
// doesn't work because of boost::units::si::kilo
static constexpr boost::units::quantity<boost::units::si::length> earth_radius_2 = (6371.0087714 * boost::units::si::kilo * boost::units::si::meters);
}
Note: I'm an embedded firmware guy trying to learn modern c++ so if you could use short simple sentences with small words in your answer, my pea sized brain would appreciate it.
This is a workaround:
static constexpr boost::units::quantity<boost::units::si::length> earth_radius_2{6371.0087714 * boost::units::si::kilo * boost::units::si::meters};
Why is this different than the code in the question?
According to the c++17 standard, initialization with a =
or direct initialization (as the solution above) are the same, if the expression on the right of =
is the same type as the variable. See the discussion here.
Apparently this is not the case here, and the conversion from the type on the right of =
to the type on the left is presumably marked as explicit
.
Here is an example.
struct X{
explicit X(int){}
explicit X(const X&) {}
};
int main()
{
X a{3};
X b = 3; // Error
}
This code does not compile because the conversion constructor from int
to X
is explicit
; as a consequence the copy initialization X b = 3
is not accepted. If you remove the explicit
keyword, then the code compiles.