Skip to content

Commit

Permalink
Merge branch 'master' of github.com:mpusz/units
Browse files Browse the repository at this point in the history
  • Loading branch information
mpusz committed Sep 17, 2024
2 parents 2e96871 + 5305de7 commit 0c9e62a
Show file tree
Hide file tree
Showing 21 changed files with 414 additions and 83 deletions.
25 changes: 22 additions & 3 deletions .github/workflows/ci-conan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,20 @@ jobs:
std_format_support: "True",
conan-config: "",
}
- {
name: "Clang-18 on Apple M1 (arm64)",
os: macos-14,
compiler:
{
type: CLANG,
version: 18,
cc: "/opt/homebrew/opt/llvm@18/bin/clang-18",
cxx: "/opt/homebrew/opt/llvm@18/bin/clang++",
},
lib: "libc++",
cxx_modules: "False",
std_format_support: "True"
}
- {
name: "Apple Clang 15",
os: macos-13,
Expand Down Expand Up @@ -196,17 +210,22 @@ jobs:
shell: bash
run: |
sudo apt install -y g++-${{ matrix.config.compiler.version }}
- name: Install Clang
if: matrix.config.compiler.type == 'CLANG'
- name: Install Clang with apt
if: matrix.config.compiler.type == 'CLANG' && matrix.config.os != 'macos-14'
shell: bash
working-directory: ${{ env.HOME }}
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh ${{ matrix.config.compiler.version }}
sudo apt install -y clang-tools-${{ matrix.config.compiler.version }}
- name: Install Clang using homebrew
if: matrix.config.compiler.type == 'CLANG' && matrix.config.os == 'macos-14'
shell: bash
run: |
brew install llvm@18
- name: Install Libc++
if: matrix.config.compiler.type == 'CLANG' && matrix.config.lib == 'libc++'
if: matrix.config.compiler.type == 'CLANG' && matrix.config.lib == 'libc++' && matrix.config.os != 'macos-14'
shell: bash
run: |
sudo apt install -y libc++-${{ matrix.config.compiler.version }}-dev libc++abi-${{ matrix.config.compiler.version }}-dev libunwind-${{ matrix.config.compiler.version }}-dev
Expand Down
25 changes: 22 additions & 3 deletions .github/workflows/ci-test-package-cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ jobs:
cxx_modules: "False",
std_format_support: "True"
}
- {
name: "Clang-18 on Apple M1 (arm64)",
os: macos-14,
compiler:
{
type: CLANG,
version: 18,
cc: "/opt/homebrew/opt/llvm@18/bin/clang-18",
cxx: "/opt/homebrew/opt/llvm@18/bin/clang++",
},
lib: "libc++",
cxx_modules: "False",
std_format_support: "True"
}
- {
name: "Apple Clang 15",
os: macos-14,
Expand Down Expand Up @@ -188,17 +202,22 @@ jobs:
shell: bash
run: |
sudo apt install -y g++-${{ matrix.config.compiler.version }}
- name: Install Clang
if: matrix.config.compiler.type == 'CLANG'
- name: Install Clang with apt
if: matrix.config.compiler.type == 'CLANG' && matrix.config.os != 'macos-14'
shell: bash
working-directory: ${{ env.HOME }}
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh ${{ matrix.config.compiler.version }}
sudo apt install -y clang-tools-${{ matrix.config.compiler.version }}
- name: Install Clang using homebrew
if: matrix.config.compiler.type == 'CLANG' && matrix.config.os == 'macos-14'
shell: bash
run: |
brew install llvm@18
- name: Install Libc++
if: matrix.config.compiler.type == 'CLANG' && matrix.config.lib == 'libc++'
if: matrix.config.compiler.type == 'CLANG' && matrix.config.lib == 'libc++' && matrix.config.os != 'macos-14'
shell: bash
run: |
sudo apt install -y libc++-${{ matrix.config.compiler.version }}-dev libc++abi-${{ matrix.config.compiler.version }}-dev libunwind-${{ matrix.config.compiler.version }}-dev
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static_assert(10 * km / (5 * km) == 2 * one);
static_assert(1000 / (1 * s) == 1 * kHz);
```
_Try it on the [Compiler Explorer](https://godbolt.org/z/8acPeq743)._
_Try it on the [Compiler Explorer](https://godbolt.org/z/fT1r4sohs)._
This library heavily uses C++20 features (concepts, classes as NTTPs, ...). Thanks to
them the user gets a powerful but still easy to use interfaces and all unit conversions
Expand Down
31 changes: 23 additions & 8 deletions docs/getting_started/cpp_compiler_support.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,29 @@
The table below provides the minimum compiler version required to compile the code using a specific
C++ feature:

| C++ Feature | C++ version | gcc | clang | apple-clang | MSVC |
|-----------------------------------------------------------|:-----------:|:----:|:-----:|:-----------:|:----:|
| **Minimum support** | 20 | 12 | 16 | 15 | None |
| **`std::format`** | 20 | 13 | 17 | None | None |
| **C++ modules** | 20 | None | 17 | None | None |
| **`import std;`** | 23 | None | 18 | None | None |
| **Static `constexpr` variables in `constexpr` functions** | 23 | 13 | 17 | None | None |
| **Explicit `this` parameter** | 23 | 14 | 18 | None | None |
| C++ Feature | C++ version | gcc | clang | apple-clang | MSVC |
|-----------------------------------------------------------|:-----------:|:----:|:-----:|:-----------:|:-----------------------------------------:|
| **Minimum support** | 20 | 12 | 16 | 15 | 194 :bug:{ title="BEWARE of MSVC Bugs!" } |
| **`std::format`** | 20 | 13 | 17 | None | 194 |
| **C++ modules** | 20 | None | 17 | None | None |
| **`import std;`** | 23 | None | 18 | None | None |
| **Static `constexpr` variables in `constexpr` functions** | 23 | 13 | 17 | None | None |
| **Explicit `this` parameter** | 23 | 14 | 18 | None | None |

??? note "MSVC bugs"

MSVC still has a poor C++20 conformance. We had to make many workarounds to our codebase to
make it compile on this compiler. Usage of such nasty preprocessor macros degrade the
readability and maintainability of our code. This is why we've applied those patches to
the main library code but not to unit tests and examples. Those still do not compile on MSVC.

Here is a list of the most important MSVC bugs:

- [Discrepancy in Behavior of operator*= and operator* for Multiplying int and double at compile time](https://developercommunity.visualstudio.com/t/Discrepancy-in-Behavior-of-operator-an/10732445)
- [Syntax error when using non-type template parameters in templated class member function](https://developercommunity.visualstudio.com/t/Syntax-error-when-using-non-type-templat/10729428)
- [Type always preferred over value when using qualified identifiers](https://developercommunity.visualstudio.com/t/Type-always-prefered-over-value-when-usi/10729382)

Please upvote them so they get a higher fixing priority at Microsoft.

!!! important

Expand Down
2 changes: 1 addition & 1 deletion docs/getting_started/look_and_feel.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Here is a small example of operations possible on scalar quantities:
static_assert(1000 / (1 * s) == 1 * kHz);
```

!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/8acPeq743)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/fT1r4sohs)"


This library requires some C++20 features ([concepts and constraints](https://en.cppreference.com/w/cpp/language/constraints),
Expand Down
33 changes: 16 additions & 17 deletions docs/users_guide/examples/avg_speed.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
tags:
- CGS System
- International System
- Text Formatting
---

# `avg_speed`

!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/TnqGa4sdn)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/v9c5T6bc4)"

Let's continue the previous example. This time, our purpose will not be to showcase as many
library features as possible, but we will scope on different interfaces one can provide
Expand All @@ -18,28 +17,28 @@ First, we either import a module or include all the necessary header files and i
the identifiers from the `mp_units` namespace:

```cpp title="avg_speed.cpp" linenums="1"
--8<-- "example/avg_speed.cpp:28:42"
--8<-- "example/avg_speed.cpp:28:46"
```

Next, we define two functions calculating average speed based on quantities of fixed units
and integral and floating-point representation types, respectively, and a third function
that we introduced in the [previous example](hello_units.md):

```cpp title="avg_speed.cpp" linenums="16"
--8<-- "example/avg_speed.cpp:44:58"
```cpp title="avg_speed.cpp" linenums="20"
--8<-- "example/avg_speed.cpp:48:62"
```

We also added a simple utility to print our results:

```cpp title="avg_speed.cpp" linenums="31"
--8<-- "example/avg_speed.cpp:60:66"
```cpp title="avg_speed.cpp" linenums="35"
--8<-- "example/avg_speed.cpp:64:70"
```

Now, let's analyze how those three utility functions behave with different sets of arguments.
First, we are going to use quantities of SI units and integral representation:

```cpp title="avg_speed.cpp" linenums="38"
--8<-- "example/avg_speed.cpp:68:82"
```cpp title="avg_speed.cpp" linenums="42"
--8<-- "example/avg_speed.cpp:72:86"
```

The above provides the following output:
Expand All @@ -61,8 +60,8 @@ representation types (the resulting speed is `108 km/h`).
The second scenario is really similar to the previous one, but this time, function arguments
have floating-point representation types:

```cpp title="avg_speed.cpp" linenums="53"
--8<-- "example/avg_speed.cpp:84:95"
```cpp title="avg_speed.cpp" linenums="57"
--8<-- "example/avg_speed.cpp:88:99"
```

Conversion from floating-point to integral representation types is
Expand All @@ -82,8 +81,8 @@ Average speed of a car that makes 220 km in 2 h is 110 km/h.
Next, let's do the same for integral and floating-point representations, but this time
using international mile:

```cpp title="avg_speed.cpp" linenums="65"
--8<-- "example/avg_speed.cpp:97:129"
```cpp title="avg_speed.cpp" linenums="69"
--8<-- "example/avg_speed.cpp:101:132"
```

One important difference here is the fact that as it is not possible to make a lossless conversion
Expand All @@ -108,8 +107,8 @@ Please note how the first and third results get truncated using integral represe

In the end, we repeat the scenario for CGS units:

```cpp title="avg_speed.cpp" linenums="97"
--8<-- "example/avg_speed.cpp:131:161"
```cpp title="avg_speed.cpp" linenums="101"
--8<-- "example/avg_speed.cpp:134:165"
```

Again, we observe `value_cast` being used in the same places and consistent truncation errors
Expand All @@ -129,6 +128,6 @@ Average speed of a car that makes 2.2e+07 cm in 7200 s is 110 km/h.

The example file ends with a simple `main()` function:

```cpp title="avg_speed.cpp" linenums="128"
--8<-- "example/avg_speed.cpp:163:"
```cpp title="avg_speed.cpp" linenums="133"
--8<-- "example/avg_speed.cpp:167:"
```
47 changes: 25 additions & 22 deletions docs/users_guide/examples/hello_units.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,32 @@ tags:

# `hello_units`

!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/bT4GGPbef)"
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/MYn5qjPzh)"

This is a really simple example showcasing the features of the **mp-units** library.

First, we either import the `mp_units` module or include the headers for:

- an International System of Quantities (ISQ)
- an International System of units (SI)
- units derived from the International Yard and Pound
- text formatting and stream output support
- an International System of Quantities (ISQ),
- an International System of units (SI),
- units derived from the International Yard and Pound,
- text formatting and stream output support.

```cpp title="hello_units.cpp" linenums="1"
--8<-- "example/hello_units.cpp:28:41"
--8<-- "example/hello_units.cpp:28:45"
```

Also, to shorten the definitions, we "import" all the symbols from the `mp_units` namespace.

```cpp title="hello_units.cpp" linenums="14"
--8<-- "example/hello_units.cpp:42:43"
```cpp title="hello_units.cpp" linenums="18"
--8<-- "example/hello_units.cpp:46:47"
```

Next, we define a simple function that calculates the average speed based on the provided
arguments of length and time:

```cpp title="hello_units.cpp" linenums="15"
--8<-- "example/hello_units.cpp:44:47"
```cpp title="hello_units.cpp" linenums="19"
--8<-- "example/hello_units.cpp:48:51"
```

The above function template takes any quantities implicitly convertible to `isq::length`
Expand All @@ -45,37 +45,37 @@ that its quantity type is implicitly convertible to `isq::speed`.
type is beneficial for users of such a function as it provides more information
of what to expect from a function than just using `auto`.

```cpp title="hello_units.cpp" linenums="19"
--8<-- "example/hello_units.cpp:49:52"
```cpp title="hello_units.cpp" linenums="23"
--8<-- "example/hello_units.cpp:53:56"
```

The above lines explicitly opt into using unit symbols from two systems of units.
As this introduces a lot of short identifiers into the current scope, it is not done
implicitly while including a header file.

```cpp title="hello_units.cpp" linenums="23"
--8<-- "example/hello_units.cpp:54:60"
```cpp title="hello_units.cpp" linenums="27"
--8<-- "example/hello_units.cpp:58:64"
```

- Lines `23` & `24` create a quantity of kind `isq::length / isq::time` with the numbers
- Lines `27` & `28` create a quantity of kind `isq::length / isq::time` with the numbers
and units provided. Such quantities can be converted or assigned to any other quantity
with a matching kind.
- Line `25` calls our function template with quantities of kind `isq::length` and
- Line `29` calls our function template with quantities of kind `isq::length` and
`isq::time` and number and units provided.
- Line `26` explicitly provides quantity types of the quantities passed to a function template.
- Line `30` explicitly provides quantity types of the quantities passed to a function template.
This time, those will not be quantity kinds anymore and will have
[more restrictive conversion rules](../framework_basics/simple_and_typed_quantities.md#quantity_cast-to-force-unsafe-conversions).
- Line `27` changes the unit of a quantity `v3` to `m / s` in a
- Line `31` changes the unit of a quantity `v3` to `m / s` in a
[value-preserving way](../framework_basics/value_conversions.md#value-preserving-conversions)
(floating-point representations are considered to be value-preserving).
- Line `28` does a similar operation, but this time, it would also succeed for
- Line `32` does a similar operation, but this time, it would also succeed for
[value-truncating cases](../framework_basics/value_conversions.md#value-truncating-conversions)
(if that was the case).
- Line `29` does a [value-truncating conversion](../framework_basics/value_conversions.md#value-truncating-conversions)
- Line `33` does a [value-truncating conversion](../framework_basics/value_conversions.md#value-truncating-conversions)
of changing the underlying representation type from `double` to `int`.

```cpp title="hello_units.cpp" linenums="30"
--8<-- "example/hello_units.cpp:62"
```cpp title="hello_units.cpp" linenums="34"
--8<-- "example/hello_units.cpp:66"
```

The above presents [various ways to print a quantity](../framework_basics/text_output.md).
Expand All @@ -86,3 +86,6 @@ Both stream insertion operations and `std::format` facilities are supported.
`MP_UNITS_STD_FMT` is used for compatibility reasons. If a specific compiler
does not support `std::format` or a user prefers to use the `{fmt}` library, this macro
will resolve to `fmt` namespace. Otherwise, the `std` namespace will be used.

More about it can be found in the [Wide Compatibility](../use_cases/wide_compatibility.md#mp_units_std_fmt)
chapter.
Loading

0 comments on commit 0c9e62a

Please sign in to comment.