mpusz / mp-units

The quantities and units library for C++
https://mpusz.github.io/mp-units/
MIT License
998 stars 79 forks source link

make_quantity fails (clang 16.0.4) #473

Closed khansson closed 10 months ago

khansson commented 1 year ago

I found I couldn't build the example files using clang 16.0.4 (running on MacOS). The error was right at initializing a quantity:

  constexpr auto v1 = 110 * (km / h);

make_quantity calls the quantity constructor. However, clang seems to think that the constructor is still private.

I can't tell if this friend declaration

template<Reference auto R2, typename Rep2>
    requires quantity<R2, std::remove_cvref_t<Rep2>>::_rep_safe_constructible_
  friend constexpr quantity<R2, std::remove_cvref_t<Rep2>> make_quantity(Rep2&&);

is actually referring to another function or is simply ignored.

So the easy hack is to make the function :

  template<typename Value>
    requires detail::RepSafeConstructibleFrom<rep, Value&&, unit>
  constexpr explicit quantity(Value&& v) : number_(std::forward<Value>(v))
  {
  }

public and then everything builds.

Notes on build:

I built mp_units just from the src directory. I compiled with c++23, and c++20 (both failed) I am not using the CMakeLists.txt using the the example directory, but writing my own directly linking against mp-units::mp-units

mpusz commented 1 year ago

Thanks for recommending this workaround. Yes, we know that the library builds only on gcc-12.2+ as stated in our docs here: https://mpusz.github.io/mp-units. Other compilers have too many bugs in C++20 support, but we try to do some workarounds to make them work. @JohelEGP is working on improving clang compilation. We did not start MSVC efforts now as this one is the hardest one to fix.

chiphogg commented 1 year ago

I ran into an issue with Aurora's original units library, the predecessor to Au. There was one compiler that struggled with the friend declaration of a function, which we had also called make_quantity().

In Au, our quantity makers are function objects. Compilers generally seem much more comfortable making a type rather than a function a friend. Then make_quantity() doesn't even need to be a friend (although we usually just use the quantity makers directly).

I don't know if there's a similar approach that'd be consistent with the idioms of mp-units, but I thought it was worth suggesting this as a possible addition to the bag of tricks.

mpusz commented 10 months ago

I believe it is fixed now.