Share your experiences writing in Cpp2! #658
Replies: 2 comments 3 replies
-
I have a group of modules layered like the STL, Here is the central piece, Cpp1 quantityexport template<const auto& R, number N> requires quantity_reference<std::remove_cvref_t<decltype(R)>> struct quantity {
using number_type = N;
N number;
static constexpr const auto& reference = R;
template<std::constructible_from<const N&> N2>
[[nodiscard]] constexpr explicit(not std::convertible_to<const N&, N2>) operator quantity<R, N2>() const {
return {convert_to<N2>(number)};
}
template<std::equality_comparable_with<N> N2>
[[nodiscard]] constexpr bool operator==(const quantity<R, N2>& r) const {
return number == r.number;
}
template<std::three_way_comparable_with<N> N2>
[[nodiscard]] constexpr std::compare_three_way_result_t<N, N2> operator<=>(const quantity<R, N2>& r) const {
return number <=> r.number;
}
constexpr quantity& operator++() & requires number_line<N> { return void(++number), *this; }
constexpr quantity& operator--() & requires number_line<N> { return void(--number), *this; }
[[nodiscard]] constexpr quantity operator++(int) & requires number_line<N> { return {number++}; }
[[nodiscard]] constexpr quantity operator--(int) & requires number_line<N> { return {number--}; }
template<compound_relative_quantity_for<N> N2> constexpr quantity& operator+=(const quantity<R, N2>& r) & {
return void(number += r.number), *this;
}
template<compound_relative_quantity_for<N> N2> constexpr quantity& operator-=(const quantity<R, N2>& r) & {
return void(number -= r.number), *this;
}
template<relative_quantity_for<N> N2>
[[nodiscard]] constexpr quantity<R, decltype(N{} + N2{})> operator+(const quantity<R, N2>& r) const {
return {number + r.number};
}
template<relative_quantity_for<N> N2>
[[nodiscard]] constexpr quantity<R, decltype(N{} - N2{})> operator-(const quantity<R, N2>& r) const {
return {number - r.number};
}
template<negatable_number N2 = N> [[nodiscard]] constexpr quantity<R, decltype(-N2{})> operator-() const {
return {-number};
}
constexpr quantity& operator*=(const compound_scalar_for<N> auto& s) & { return void(number *= s), *this; }
constexpr quantity& operator/=(const compound_scalar_for<N> auto& s) & { return void(number /= s), *this; }
constexpr quantity& operator%=(const compound_modulus_for<N> auto& d) & { return void(number %= d), *this; }
template<compound_modulus_for<N> N2> constexpr quantity& operator%=(const quantity<R, N2>& r) & {
return void(number %= r.number), *this;
}
[[nodiscard]] friend constexpr auto operator*(const quantity& q, const scalar_for<N> auto& s)
-> quantity<R, decltype(N{} * s)> {
return {q.number * s};
}
[[nodiscard]] friend constexpr auto operator*(const scalar_for<N> auto& s, const quantity& q)
-> quantity<R, decltype(s * N{})> {
return {s * q.number};
}
[[nodiscard]] constexpr auto operator/(const scalar_for<N> auto& s) const -> quantity<R, decltype(N{} / s)> {
return {number / s};
}
template<std::common_with<N> N2>
[[nodiscard]] constexpr decltype(N{} / N2{}) operator/(const quantity<R, N2>& r) const {
return number / r.number;
}
[[nodiscard]] constexpr auto operator%(const modulus_for<N> auto& m) const -> quantity<R, decltype(N{} % m)> {
return {number % m};
}
template<modulus_for<N> N2>
[[nodiscard]] constexpr quantity<R, decltype(N{} % N2{})> operator%(const quantity<R, N2>& m) const {
return {number % m.number};
}
}; I rewrote Cpp2 quantity
I'm not done yet (e.g., Cpp2 snapshot of an homogeneous and unconstrained quantityexport quantity: @struct @ordered <Name, Unit, Number: type> type = {
name_type: type == Name;
unit_type: type == Unit;
number_type: type == Number;
name: JEGP_QTY_NAME_MEM_TYPE = missing_name_in_initializer(this);
number: Number = missing_number_in_initializer(this);
unit: JEGP_QTY_UNIT_MEM_TYPE = missing_unit_in_initializer(this);
operator+=: (inout this, that) -> forward quantity = {
_ = number += that.number;
return this;
}
operator-=: (inout this, that) -> forward quantity = {
_ = number -= that.number;
return this;
}
operator+: (this, that) -> quantity = (name, number + that.number, unit);
operator-: (this, that) -> quantity = (name, number - that.number, unit);
operator*: (this, r: Number) -> quantity = (name, number * r, unit);
operator/: (this, r: Number) -> quantity = (name, number / r, unit);
}
export to: <Number> (forward q: quantity) -> _ //
= :quantity = (q.name, cpp2::unsafe_narrow<Number>(forward q.number), q.unit); As I go back to improve Granted, some of these issues can be amortized in Cpp1 with proper formatting. // Cpp1.
template<class T> [[nodiscard]] T // One extra line.
f();
// Cpp2.
f: <T> () -> T;
// Cpp1.
template<class T> // One extra line.
[[nodiscard]] T
g();
// Cpp2.
g: <T> ()
-> T; Where Cpp2 has fallen short, most of the time I have opened issues #define QTY_NAME_MEM_TYPE [[no_unique_address]] name_type And because there's no way of spelling post-increment or post-decrement, // Cpp1.
[[nodiscard]] constexpr quantity operator++(int) & requires number_line<N> { return {number++}; }
// Cpp2 is:
operator++: (inout this, _: int) -> quantity requires number_line<Number> = {
res := this;
_ = this++;
return res;
}
// Cpp2 could have been (where `INC(x)` is Cpp1 `x++`):
operator++: (inout this, _: int) -> quantity requires number_line<Number> = (name, INC(number), unit); When rewriting the tests for the struct number_line_5 : number_line<number_line_5> {
number_line_5& operator++() &;
number_line_5& operator++(int);
};
struct number_line_6 : number_line<number_line_6> {
number_line_6& operator++() &;
number_line_6& operator++(int) &;
};
static_assert(not waarudo::number_line<number_line_5>, "No `lvalue++`.");
static_assert(not waarudo::number_line<number_line_6>, "The type of `lvalue++` is not `number_line_6`."); This is how I rewrote it in Cpp2.
These test cases actually pass for the same reason, unlike the assertions document. |
Beta Was this translation helpful? Give feedback.
-
lefticus/cpp_weekly#297 presents a comparison in Cpp1
|
Beta Was this translation helpful? Give feedback.
-
From short thoughts to long articles hosted elsewhere.
Beta Was this translation helpful? Give feedback.
All reactions