Skip to content

Commit

Permalink
Merge pull request #84 from elbeno/integral-constant
Browse files Browse the repository at this point in the history
✨ Add `_c` for integral constants
  • Loading branch information
elbeno authored Apr 16, 2024
2 parents 0c256cd + 0e2d43d commit 7808e7a
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 177 deletions.
4 changes: 4 additions & 0 deletions docs/ct_string.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ struct named_thing {

NOTE: `size` and `empty` are always available as `constexpr`.

NOTE: `_cts` is a user-defined literal declared in
`stdx::literals::ct_string_literals`, where both `literals` and
`ct_string_literals` are inline namespaces.

CAUTION: `ct_string` stores an internal array (`value`) which includes the null
terminator for the string. The `size` reported by the `ct_string` is one less
than the size of the internal array. Thus the `begin`, `end` and `size` of a
Expand Down
1 change: 1 addition & 0 deletions docs/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ include::tuple.adoc[]
include::tuple_algorithms.adoc[]
include::tuple_destructure.adoc[]
include::type_traits.adoc[]
include::udls.adoc[]
include::utility.adoc[]
1 change: 1 addition & 0 deletions docs/intro.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ The following headers are available:
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/tuple_algorithms.hpp[`tuple_algorithms.hpp`]
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/tuple_destructure.hpp[`tuple_destructure.hpp`]
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/type_traits.hpp[`type_traits.hpp`]
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/udls.hpp[`udls.hpp`]
* https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/utility.hpp[`utility.hpp`]
70 changes: 70 additions & 0 deletions docs/udls.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@

== `udls.hpp`

NOTE: Taking a cue from the standard, all UDLs in `stdx` are declared in inline
namespaces - typically `stdx::literals`.

=== Useful user-defined literals

`udls.hpp` contains a few handy user-defined literals so that code using boolean
or small index values can be more expressive at the call site than just using
bare `true`, `false`, or `0` through `9`. This also makes it safer to use
templates with `bool` or integral parameters.

[source,cpp]
----
using namespace stdx::literals;
template <bool X>
struct my_type { ... };
using my_type_with_X = my_type<"X"_true>;
using my_type_without_X = my_type<"X"_false>;
using my_type_with_X_alt = my_type<"X"_b>;
using my_type_without_X_alt = my_type<not "X"_b>;
auto t = stdx::tuple{1, true, 3.14f};
auto value = get<"X"_1>(t); // true
----

NOTE: The `_N` literals each return a `std::integral_constant<std::size_t, N>`.
This is implicitly convertible to a `std::size_t`.

There are also some UDLs that are useful when specifying sizes in bytes:

[source,cpp]
----
using namespace stdx::literals;
// decimal SI prefixes
constexpr auto a = 1_k; // 1,000
constexpr auto b = 1_M; // 1,000,000
constexpr auto c = 1_G; // 1,000,000,000
// binary equivalents
constexpr auto d = 1_ki; // 1,024
constexpr auto e = 1_Mi; // 1,048,567
constexpr auto f = 1_Gi; // 1,073,741,824
----

=== Integral and enum values

`_c` is a variable template whose value is a `std::integral_constant` with inferred type.

[source,cpp]
----
constexpr auto i = stdx::_c<1>; // std::integral_constant<int, 1>
enum struct E { value = 1 };
constexpr auto e = stdx::_c<E::value>; // std::integral_constant<E, E::value>
----

`_c` is also a user-defined literal that can be used to make a `std::integral_constant<std::uint32_t, N>`.

[source,cpp]
----
using namespace stdx::literals;
constexpr auto i = 1_c; // std::integral_constant<std::uint32_t, 1>
----
44 changes: 0 additions & 44 deletions docs/utility.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -192,47 +192,3 @@ https://en.cppreference.com/w/cpp/utility/unreachable[`std::unreachable`].
// undefined behaviour
}
----

=== User-defined literals

`utility.hpp` also contains a few handy user-defined literals so that code using
boolean or small index values can be more expressive at the call site than just
using bare `true`, `false`, or `0` through `9`. This also makes it safer to use
templates with `bool` or integral parameters.

[source,cpp]
----
using namespace stdx::literals;
template <bool X>
struct my_type { ... };
using my_type_with_X = my_type<"X"_true>;
using my_type_without_X = my_type<"X"_false>;
using my_type_with_X_alt = my_type<"X"_b>;
using my_type_without_X_alt = my_type<not "X"_b>;
auto t = stdx::tuple{1, true, 3.14f};
auto value = get<"X"_1>(t); // true
----

NOTE: The `_N` literals each return a `std::integral_constant<std::size_t, N>`.
This is implicitly convertible to a `std::size_t`.

There are also some UDLs that are useful when specifying sizes in bytes:

[source,cpp]
----
using namespace stdx::literals;
// decimal SI prefixes
constexpr auto a = 1_k; // 1,000
constexpr auto b = 1_M; // 1,000,000
constexpr auto c = 1_G; // 1,000,000,000
// binary equivalents
constexpr auto d = 1_ki; // 1,024
constexpr auto e = 1_Mi; // 1,048,567
constexpr auto f = 1_Gi; // 1,073,741,824
----
18 changes: 1 addition & 17 deletions include/stdx/bitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <stdx/bit.hpp>
#include <stdx/compiler.hpp>
#include <stdx/type_traits.hpp>
#include <stdx/udls.hpp>

#include <algorithm>
#include <array>
Expand All @@ -20,10 +21,6 @@ constexpr inline auto place_bits = place_bits_t{};
struct all_bits_t {};
constexpr inline auto all_bits = all_bits_t{};

enum struct lsb_t : std::size_t {};
enum struct msb_t : std::size_t {};
enum struct length_t : std::size_t {};

namespace detail {
template <std::size_t N, typename StorageElem> class bitset {
constexpr static auto storage_elem_size =
Expand Down Expand Up @@ -412,18 +409,5 @@ template <std::size_t N, typename StorageElem = void>
using bitset =
detail::bitset<N, decltype(detail::select_storage<N, StorageElem>())>;

namespace literals {
// NOLINTBEGIN(google-runtime-int)
CONSTEVAL auto operator""_lsb(unsigned long long int n) -> lsb_t {
return static_cast<lsb_t>(n);
}
CONSTEVAL auto operator""_msb(unsigned long long int n) -> msb_t {
return static_cast<msb_t>(n);
}
CONSTEVAL auto operator""_len(unsigned long long int n) -> length_t {
return static_cast<length_t>(n);
}
// NOLINTEND(google-runtime-int)
} // namespace literals
} // namespace v1
} // namespace stdx
5 changes: 4 additions & 1 deletion include/stdx/ct_string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,14 @@ template <std::size_t N, std::size_t M>
return ret;
}

namespace ct_string_literals {
inline namespace literals {
inline namespace ct_string_literals {
template <typename T, T... Cs> CONSTEVAL auto operator""_cts() {
return ct_string<sizeof...(Cs) + 1U>{{Cs..., 0}};
}
} // namespace ct_string_literals
} // namespace literals

} // namespace v1
} // namespace stdx

Expand Down
69 changes: 25 additions & 44 deletions include/stdx/tuple.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#if __cplusplus >= 202002L

#include <stdx/udls.hpp>

#include <array>
#include <concepts>
#include <cstddef>
Expand All @@ -13,8 +15,16 @@
namespace stdx {
inline namespace v1 {

template <std::size_t> struct index_constant;
template <std::size_t I> constexpr static index_constant<I> *index{};
template <std::size_t I>
using index_constant = std::integral_constant<std::size_t, I>;
template <std::size_t I> constexpr static index_constant<I> index{};

inline namespace literals {
template <char... Chars> CONSTEVAL auto operator""_idx() {
return index<detail::decimal<std::size_t, Chars...>()>;
}
} // namespace literals

template <typename> struct tag_constant;
template <typename T> constexpr static tag_constant<T> *tag{};

Expand Down Expand Up @@ -44,19 +54,6 @@ template <auto I, typename... Ts> constexpr auto index_out_of_bounds() {
}
} // namespace error

namespace literals {
template <char... Chars>
requires(... and (Chars >= '0' and Chars <= '9'))
constexpr auto operator""_idx() {
constexpr auto n = [] {
auto x = std::size_t{};
((x *= 10, x += Chars - '0'), ...);
return x;
}();
return index<n>;
}
} // namespace literals

namespace detail {
template <std::size_t, typename...> struct element;

Expand All @@ -68,15 +65,15 @@ concept nonderivable = not std::is_class_v<T>;
template <std::size_t Index, nonderivable T, typename... Ts>
struct element<Index, T, Ts...> {
[[nodiscard]] constexpr auto
ugly_iGet_clvr(index_constant<Index> *) const & noexcept -> T const & {
ugly_iGet_clvr(index_constant<Index>) const & noexcept -> T const & {
return value;
}
[[nodiscard]] constexpr auto
ugly_iGet_lvr(index_constant<Index> *) & noexcept -> T & {
[[nodiscard]] constexpr auto ugly_iGet_lvr(index_constant<Index>) & noexcept
-> T & {
return value;
}
[[nodiscard]] constexpr auto
ugly_iGet_rvr(index_constant<Index> *) && noexcept -> T && {
ugly_iGet_rvr(index_constant<Index>) && noexcept -> T && {
return std::forward<T>(value);
}

Expand All @@ -99,7 +96,7 @@ struct element<Index, T, Ts...> {
return std::forward<T>(value);
}

constexpr static auto ugly_Value(index_constant<Index> *) -> T;
constexpr static auto ugly_Value(index_constant<Index>) -> T;
constexpr auto ugly_Value_clvr() const & -> T const & { return value; }
constexpr auto ugly_Value_lvr() & -> T & { return value; }
constexpr auto ugly_Value_rvr() && -> T && {
Expand All @@ -121,15 +118,15 @@ struct element<Index, T, Ts...> : T {
constexpr static auto ugly_Index = Index;

[[nodiscard]] constexpr auto
ugly_iGet_clvr(index_constant<Index> *) const & noexcept -> T const & {
ugly_iGet_clvr(index_constant<Index>) const & noexcept -> T const & {
return *this;
}
[[nodiscard]] constexpr auto
ugly_iGet_lvr(index_constant<Index> *) & noexcept -> T & {
[[nodiscard]] constexpr auto ugly_iGet_lvr(index_constant<Index>) & noexcept
-> T & {
return *this;
}
[[nodiscard]] constexpr auto
ugly_iGet_rvr(index_constant<Index> *) && noexcept -> T && {
ugly_iGet_rvr(index_constant<Index>) && noexcept -> T && {
return std::move(*this);
}

Expand All @@ -152,7 +149,7 @@ struct element<Index, T, Ts...> : T {
return std::move(*this);
}

constexpr static auto ugly_Value(index_constant<Index> *) -> T;
constexpr static auto ugly_Value(index_constant<Index>) -> T;
constexpr auto ugly_Value_clvr() const & -> T const & { return *this; }
constexpr auto ugly_Value_lvr() & -> T & { return *this; }
constexpr auto ugly_Value_rvr() && -> T && { return std::move(*this); }
Expand Down Expand Up @@ -260,7 +257,7 @@ struct tuple_impl<std::index_sequence<Is...>, index_function_list<Fs...>, Ts...>

template <std::size_t I>
[[nodiscard]] constexpr auto
operator[](index_constant<I> *i) const & -> decltype(auto) {
operator[](index_constant<I> i) const & -> decltype(auto) {
if constexpr (I >= sizeof...(Ts)) {
error::index_out_of_bounds<I, Ts...>();
} else {
Expand All @@ -269,7 +266,7 @@ struct tuple_impl<std::index_sequence<Is...>, index_function_list<Fs...>, Ts...>
}
template <std::size_t I>
[[nodiscard]] constexpr auto
operator[](index_constant<I> *i) & -> decltype(auto) {
operator[](index_constant<I> i) & -> decltype(auto) {
if constexpr (I >= sizeof...(Ts)) {
error::index_out_of_bounds<I, Ts...>();
} else {
Expand All @@ -278,30 +275,14 @@ struct tuple_impl<std::index_sequence<Is...>, index_function_list<Fs...>, Ts...>
}
template <std::size_t I>
[[nodiscard]] constexpr auto
operator[](index_constant<I> *i) && -> decltype(auto) {
operator[](index_constant<I> i) && -> decltype(auto) {
if constexpr (I >= sizeof...(Ts)) {
error::index_out_of_bounds<I, Ts...>();
} else {
return std::move(*this).ugly_iGet_rvr(i);
}
}

template <std::size_t I>
[[nodiscard]] constexpr auto operator[](
std::integral_constant<std::size_t, I>) const & -> decltype(auto) {
return this->operator[](index<I>);
}
template <std::size_t I>
[[nodiscard]] constexpr auto
operator[](std::integral_constant<std::size_t, I>) & -> decltype(auto) {
return this->operator[](index<I>);
}
template <std::size_t I>
[[nodiscard]] constexpr auto
operator[](std::integral_constant<std::size_t, I>) && -> decltype(auto) {
return std::move(*this).operator[](index<I>);
}

constexpr auto ugly_tGet_clvr(auto idx) const & -> void {
error::type_not_found<decltype(idx), Ts...>();
}
Expand Down
9 changes: 6 additions & 3 deletions include/stdx/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
namespace stdx {
inline namespace v1 {

template <typename E>
constexpr auto to_underlying(E e) noexcept -> std::underlying_type_t<E> {
return static_cast<std::underlying_type_t<E>>(e);
template <typename E> constexpr auto to_underlying(E e) noexcept {
if constexpr (std::is_enum_v<E>) {
return static_cast<std::underlying_type_t<E>>(e);
} else {
return e;
}
}

template <typename T> struct remove_cvref {
Expand Down
Loading

0 comments on commit 7808e7a

Please sign in to comment.