Search code examples
c++boostconstexpr

How to use boost unit prefixes in a constexpr


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.


Solution

  • 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.