Loading include/ftl/Flags.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -209,12 +209,12 @@ namespace flag_operators { template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> inline Flags<F> operator~(F f) { inline Flags<F> operator~(F f) { return static_cast<F>(~ftl::enum_cast(f)); return static_cast<F>(~ftl::to_underlying(f)); } } template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> Flags<F> operator|(F lhs, F rhs) { Flags<F> operator|(F lhs, F rhs) { return static_cast<F>(ftl::enum_cast(lhs) | ftl::enum_cast(rhs)); return static_cast<F>(ftl::to_underlying(lhs) | ftl::to_underlying(rhs)); } } } // namespace flag_operators } // namespace flag_operators Loading include/ftl/array_traits.h→include/ftl/details/array_traits.h +3 −3 Original line number Original line Diff line number Diff line Loading @@ -21,9 +21,9 @@ #include <new> #include <new> #include <type_traits> #include <type_traits> #define FTL_ARRAY_TRAIT(T, U) using U = typename ArrayTraits<T>::U #define FTL_ARRAY_TRAIT(T, U) using U = typename details::ArrayTraits<T>::U namespace android::ftl { namespace android::ftl::details { template <typename T> template <typename T> struct ArrayTraits { struct ArrayTraits { Loading Loading @@ -132,4 +132,4 @@ struct ArrayComparators { } } }; }; } // namespace android::ftl } // namespace android::ftl::details include/ftl/enum.h +16 −14 Original line number Original line Diff line number Diff line Loading @@ -87,11 +87,13 @@ inline constexpr bool is_scoped_enum_v = is_scoped_enum<T>::value; // Shorthand for casting an enumerator to its integral value. // Shorthand for casting an enumerator to its integral value. // // // TODO: Replace with std::to_underlying in C++23. // // enum class E { A, B, C }; // enum class E { A, B, C }; // static_assert(ftl::enum_cast(E::B) == 1); // static_assert(ftl::to_underlying(E::B) == 1); // // template <typename E> template <typename E> constexpr auto enum_cast(E v) { constexpr auto to_underlying(E v) { return static_cast<std::underlying_type_t<E>>(v); return static_cast<std::underlying_type_t<E>>(v); } } Loading Loading @@ -137,19 +139,19 @@ struct enum_end { template <typename E> template <typename E> struct enum_end<E, std::void_t<decltype(E::ftl_last)>> { struct enum_end<E, std::void_t<decltype(E::ftl_last)>> { static constexpr E value = E{enum_cast(E::ftl_last) + 1}; static constexpr E value = E{to_underlying(E::ftl_last) + 1}; }; }; template <typename E> template <typename E> inline constexpr E enum_end_v = enum_end<E>::value; inline constexpr E enum_end_v = enum_end<E>::value; template <typename E> template <typename E> inline constexpr E enum_last_v = E{enum_cast(enum_end_v<E>) - 1}; inline constexpr E enum_last_v = E{to_underlying(enum_end_v<E>) - 1}; template <typename E> template <typename E> struct enum_size { struct enum_size { static constexpr auto kBegin = enum_cast(enum_begin_v<E>); static constexpr auto kBegin = to_underlying(enum_begin_v<E>); static constexpr auto kEnd = enum_cast(enum_end_v<E>); static constexpr auto kEnd = to_underlying(enum_end_v<E>); static_assert(kBegin < kEnd, "Invalid range"); static_assert(kBegin < kEnd, "Invalid range"); static constexpr std::size_t value = kEnd - kBegin; static constexpr std::size_t value = kEnd - kBegin; Loading @@ -174,7 +176,7 @@ struct EnumRange; template <typename E, template <E> class F, typename T, T... Vs> template <typename E, template <E> class F, typename T, T... Vs> struct EnumRange<E, F, std::integer_sequence<T, Vs...>> { struct EnumRange<E, F, std::integer_sequence<T, Vs...>> { static constexpr auto kBegin = enum_cast(enum_begin_v<E>); static constexpr auto kBegin = to_underlying(enum_begin_v<E>); static constexpr auto kSize = enum_size_v<E>; static constexpr auto kSize = enum_size_v<E>; using R = decltype(F<E{}>::value); using R = decltype(F<E{}>::value); Loading @@ -194,7 +196,7 @@ struct FlagName { using E = decltype(I); using E = decltype(I); using U = std::underlying_type_t<E>; using U = std::underlying_type_t<E>; static constexpr E V{U{1} << enum_cast(I)}; static constexpr E V{U{1} << to_underlying(I)}; static constexpr auto value = ftl_enum<E, V>(); static constexpr auto value = ftl_enum<E, V>(); }; }; Loading Loading @@ -237,10 +239,10 @@ constexpr std::string_view enum_name() { // // template <typename E> template <typename E> constexpr std::optional<std::string_view> enum_name(E v) { constexpr std::optional<std::string_view> enum_name(E v) { const auto value = enum_cast(v); const auto value = to_underlying(v); constexpr auto kBegin = enum_cast(enum_begin_v<E>); constexpr auto kBegin = to_underlying(enum_begin_v<E>); constexpr auto kLast = enum_cast(enum_last_v<E>); constexpr auto kLast = to_underlying(enum_last_v<E>); if (value < kBegin || value > kLast) return {}; if (value < kBegin || value > kLast) return {}; constexpr auto kRange = details::EnumRange<E, details::EnumName>{}; constexpr auto kRange = details::EnumRange<E, details::EnumName>{}; Loading @@ -256,7 +258,7 @@ constexpr std::optional<std::string_view> enum_name(E v) { // // template <typename E> template <typename E> constexpr std::optional<std::string_view> flag_name(E v) { constexpr std::optional<std::string_view> flag_name(E v) { const auto value = enum_cast(v); const auto value = to_underlying(v); // TODO: Replace with std::popcount and std::countr_zero in C++20. // TODO: Replace with std::popcount and std::countr_zero in C++20. if (__builtin_popcountl(value) != 1) return {}; if (__builtin_popcountl(value) != 1) return {}; Loading @@ -277,7 +279,7 @@ inline std::string enum_string(E v) { if (const auto name = enum_name(v)) { if (const auto name = enum_name(v)) { return std::string(*name); return std::string(*name); } } return to_string(enum_cast(v)); return to_string(to_underlying(v)); } } // Returns a stringified flag enumerator, or its integral value if not named. // Returns a stringified flag enumerator, or its integral value if not named. Loading @@ -293,7 +295,7 @@ inline std::string flag_string(E v) { return std::string(*name); return std::string(*name); } } constexpr auto radix = sizeof(E) == 1 ? Radix::kBin : Radix::kHex; constexpr auto radix = sizeof(E) == 1 ? Radix::kBin : Radix::kHex; return to_string(enum_cast(v), radix); return to_string(to_underlying(v), radix); } } } // namespace android::ftl } // namespace android::ftl include/ftl/small_vector.h +6 −6 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,7 @@ #pragma once #pragma once #include <ftl/array_traits.h> #include <ftl/details/array_traits.h> #include <ftl/static_vector.h> #include <ftl/static_vector.h> #include <algorithm> #include <algorithm> Loading Loading @@ -73,7 +73,7 @@ struct is_small_vector; // assert(strings[2] == "???"); // assert(strings[2] == "???"); // // template <typename T, std::size_t N> template <typename T, std::size_t N> class SmallVector final : ArrayTraits<T>, ArrayComparators<SmallVector> { class SmallVector final : details::ArrayTraits<T>, details::ArrayComparators<SmallVector> { using Static = StaticVector<T, N>; using Static = StaticVector<T, N>; using Dynamic = SmallVector<T, 0>; using Dynamic = SmallVector<T, 0>; Loading Loading @@ -266,12 +266,12 @@ class SmallVector final : ArrayTraits<T>, ArrayComparators<SmallVector> { // Partial specialization without static storage. // Partial specialization without static storage. template <typename T> template <typename T> class SmallVector<T, 0> final : ArrayTraits<T>, class SmallVector<T, 0> final : details::ArrayTraits<T>, ArrayIterators<SmallVector<T, 0>, T>, details::ArrayIterators<SmallVector<T, 0>, T>, std::vector<T> { std::vector<T> { using ArrayTraits<T>::construct_at; using details::ArrayTraits<T>::construct_at; using Iter = ArrayIterators<SmallVector, T>; using Iter = details::ArrayIterators<SmallVector, T>; using Impl = std::vector<T>; using Impl = std::vector<T>; friend Iter; friend Iter; Loading include/ftl/static_vector.h +6 −6 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,7 @@ #pragma once #pragma once #include <ftl/array_traits.h> #include <ftl/details/array_traits.h> #include <ftl/initializer_list.h> #include <ftl/initializer_list.h> #include <algorithm> #include <algorithm> Loading Loading @@ -73,14 +73,14 @@ constexpr struct IteratorRangeTag { // assert(strings[2] == "???"); // assert(strings[2] == "???"); // // template <typename T, std::size_t N> template <typename T, std::size_t N> class StaticVector final : ArrayTraits<T>, class StaticVector final : details::ArrayTraits<T>, ArrayIterators<StaticVector<T, N>, T>, details::ArrayIterators<StaticVector<T, N>, T>, ArrayComparators<StaticVector> { details::ArrayComparators<StaticVector> { static_assert(N > 0); static_assert(N > 0); using ArrayTraits<T>::construct_at; using details::ArrayTraits<T>::construct_at; using Iter = ArrayIterators<StaticVector, T>; using Iter = details::ArrayIterators<StaticVector, T>; friend Iter; friend Iter; // There is ambiguity when constructing from two iterator-like elements like pointers: // There is ambiguity when constructing from two iterator-like elements like pointers: Loading Loading
include/ftl/Flags.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -209,12 +209,12 @@ namespace flag_operators { template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> inline Flags<F> operator~(F f) { inline Flags<F> operator~(F f) { return static_cast<F>(~ftl::enum_cast(f)); return static_cast<F>(~ftl::to_underlying(f)); } } template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>> Flags<F> operator|(F lhs, F rhs) { Flags<F> operator|(F lhs, F rhs) { return static_cast<F>(ftl::enum_cast(lhs) | ftl::enum_cast(rhs)); return static_cast<F>(ftl::to_underlying(lhs) | ftl::to_underlying(rhs)); } } } // namespace flag_operators } // namespace flag_operators Loading
include/ftl/array_traits.h→include/ftl/details/array_traits.h +3 −3 Original line number Original line Diff line number Diff line Loading @@ -21,9 +21,9 @@ #include <new> #include <new> #include <type_traits> #include <type_traits> #define FTL_ARRAY_TRAIT(T, U) using U = typename ArrayTraits<T>::U #define FTL_ARRAY_TRAIT(T, U) using U = typename details::ArrayTraits<T>::U namespace android::ftl { namespace android::ftl::details { template <typename T> template <typename T> struct ArrayTraits { struct ArrayTraits { Loading Loading @@ -132,4 +132,4 @@ struct ArrayComparators { } } }; }; } // namespace android::ftl } // namespace android::ftl::details
include/ftl/enum.h +16 −14 Original line number Original line Diff line number Diff line Loading @@ -87,11 +87,13 @@ inline constexpr bool is_scoped_enum_v = is_scoped_enum<T>::value; // Shorthand for casting an enumerator to its integral value. // Shorthand for casting an enumerator to its integral value. // // // TODO: Replace with std::to_underlying in C++23. // // enum class E { A, B, C }; // enum class E { A, B, C }; // static_assert(ftl::enum_cast(E::B) == 1); // static_assert(ftl::to_underlying(E::B) == 1); // // template <typename E> template <typename E> constexpr auto enum_cast(E v) { constexpr auto to_underlying(E v) { return static_cast<std::underlying_type_t<E>>(v); return static_cast<std::underlying_type_t<E>>(v); } } Loading Loading @@ -137,19 +139,19 @@ struct enum_end { template <typename E> template <typename E> struct enum_end<E, std::void_t<decltype(E::ftl_last)>> { struct enum_end<E, std::void_t<decltype(E::ftl_last)>> { static constexpr E value = E{enum_cast(E::ftl_last) + 1}; static constexpr E value = E{to_underlying(E::ftl_last) + 1}; }; }; template <typename E> template <typename E> inline constexpr E enum_end_v = enum_end<E>::value; inline constexpr E enum_end_v = enum_end<E>::value; template <typename E> template <typename E> inline constexpr E enum_last_v = E{enum_cast(enum_end_v<E>) - 1}; inline constexpr E enum_last_v = E{to_underlying(enum_end_v<E>) - 1}; template <typename E> template <typename E> struct enum_size { struct enum_size { static constexpr auto kBegin = enum_cast(enum_begin_v<E>); static constexpr auto kBegin = to_underlying(enum_begin_v<E>); static constexpr auto kEnd = enum_cast(enum_end_v<E>); static constexpr auto kEnd = to_underlying(enum_end_v<E>); static_assert(kBegin < kEnd, "Invalid range"); static_assert(kBegin < kEnd, "Invalid range"); static constexpr std::size_t value = kEnd - kBegin; static constexpr std::size_t value = kEnd - kBegin; Loading @@ -174,7 +176,7 @@ struct EnumRange; template <typename E, template <E> class F, typename T, T... Vs> template <typename E, template <E> class F, typename T, T... Vs> struct EnumRange<E, F, std::integer_sequence<T, Vs...>> { struct EnumRange<E, F, std::integer_sequence<T, Vs...>> { static constexpr auto kBegin = enum_cast(enum_begin_v<E>); static constexpr auto kBegin = to_underlying(enum_begin_v<E>); static constexpr auto kSize = enum_size_v<E>; static constexpr auto kSize = enum_size_v<E>; using R = decltype(F<E{}>::value); using R = decltype(F<E{}>::value); Loading @@ -194,7 +196,7 @@ struct FlagName { using E = decltype(I); using E = decltype(I); using U = std::underlying_type_t<E>; using U = std::underlying_type_t<E>; static constexpr E V{U{1} << enum_cast(I)}; static constexpr E V{U{1} << to_underlying(I)}; static constexpr auto value = ftl_enum<E, V>(); static constexpr auto value = ftl_enum<E, V>(); }; }; Loading Loading @@ -237,10 +239,10 @@ constexpr std::string_view enum_name() { // // template <typename E> template <typename E> constexpr std::optional<std::string_view> enum_name(E v) { constexpr std::optional<std::string_view> enum_name(E v) { const auto value = enum_cast(v); const auto value = to_underlying(v); constexpr auto kBegin = enum_cast(enum_begin_v<E>); constexpr auto kBegin = to_underlying(enum_begin_v<E>); constexpr auto kLast = enum_cast(enum_last_v<E>); constexpr auto kLast = to_underlying(enum_last_v<E>); if (value < kBegin || value > kLast) return {}; if (value < kBegin || value > kLast) return {}; constexpr auto kRange = details::EnumRange<E, details::EnumName>{}; constexpr auto kRange = details::EnumRange<E, details::EnumName>{}; Loading @@ -256,7 +258,7 @@ constexpr std::optional<std::string_view> enum_name(E v) { // // template <typename E> template <typename E> constexpr std::optional<std::string_view> flag_name(E v) { constexpr std::optional<std::string_view> flag_name(E v) { const auto value = enum_cast(v); const auto value = to_underlying(v); // TODO: Replace with std::popcount and std::countr_zero in C++20. // TODO: Replace with std::popcount and std::countr_zero in C++20. if (__builtin_popcountl(value) != 1) return {}; if (__builtin_popcountl(value) != 1) return {}; Loading @@ -277,7 +279,7 @@ inline std::string enum_string(E v) { if (const auto name = enum_name(v)) { if (const auto name = enum_name(v)) { return std::string(*name); return std::string(*name); } } return to_string(enum_cast(v)); return to_string(to_underlying(v)); } } // Returns a stringified flag enumerator, or its integral value if not named. // Returns a stringified flag enumerator, or its integral value if not named. Loading @@ -293,7 +295,7 @@ inline std::string flag_string(E v) { return std::string(*name); return std::string(*name); } } constexpr auto radix = sizeof(E) == 1 ? Radix::kBin : Radix::kHex; constexpr auto radix = sizeof(E) == 1 ? Radix::kBin : Radix::kHex; return to_string(enum_cast(v), radix); return to_string(to_underlying(v), radix); } } } // namespace android::ftl } // namespace android::ftl
include/ftl/small_vector.h +6 −6 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,7 @@ #pragma once #pragma once #include <ftl/array_traits.h> #include <ftl/details/array_traits.h> #include <ftl/static_vector.h> #include <ftl/static_vector.h> #include <algorithm> #include <algorithm> Loading Loading @@ -73,7 +73,7 @@ struct is_small_vector; // assert(strings[2] == "???"); // assert(strings[2] == "???"); // // template <typename T, std::size_t N> template <typename T, std::size_t N> class SmallVector final : ArrayTraits<T>, ArrayComparators<SmallVector> { class SmallVector final : details::ArrayTraits<T>, details::ArrayComparators<SmallVector> { using Static = StaticVector<T, N>; using Static = StaticVector<T, N>; using Dynamic = SmallVector<T, 0>; using Dynamic = SmallVector<T, 0>; Loading Loading @@ -266,12 +266,12 @@ class SmallVector final : ArrayTraits<T>, ArrayComparators<SmallVector> { // Partial specialization without static storage. // Partial specialization without static storage. template <typename T> template <typename T> class SmallVector<T, 0> final : ArrayTraits<T>, class SmallVector<T, 0> final : details::ArrayTraits<T>, ArrayIterators<SmallVector<T, 0>, T>, details::ArrayIterators<SmallVector<T, 0>, T>, std::vector<T> { std::vector<T> { using ArrayTraits<T>::construct_at; using details::ArrayTraits<T>::construct_at; using Iter = ArrayIterators<SmallVector, T>; using Iter = details::ArrayIterators<SmallVector, T>; using Impl = std::vector<T>; using Impl = std::vector<T>; friend Iter; friend Iter; Loading
include/ftl/static_vector.h +6 −6 Original line number Original line Diff line number Diff line Loading @@ -16,7 +16,7 @@ #pragma once #pragma once #include <ftl/array_traits.h> #include <ftl/details/array_traits.h> #include <ftl/initializer_list.h> #include <ftl/initializer_list.h> #include <algorithm> #include <algorithm> Loading Loading @@ -73,14 +73,14 @@ constexpr struct IteratorRangeTag { // assert(strings[2] == "???"); // assert(strings[2] == "???"); // // template <typename T, std::size_t N> template <typename T, std::size_t N> class StaticVector final : ArrayTraits<T>, class StaticVector final : details::ArrayTraits<T>, ArrayIterators<StaticVector<T, N>, T>, details::ArrayIterators<StaticVector<T, N>, T>, ArrayComparators<StaticVector> { details::ArrayComparators<StaticVector> { static_assert(N > 0); static_assert(N > 0); using ArrayTraits<T>::construct_at; using details::ArrayTraits<T>::construct_at; using Iter = ArrayIterators<StaticVector, T>; using Iter = details::ArrayIterators<StaticVector, T>; friend Iter; friend Iter; // There is ambiguity when constructing from two iterator-like elements like pointers: // There is ambiguity when constructing from two iterator-like elements like pointers: Loading