diff --git a/include/siplasplas/reflection/static/enum.hpp b/include/siplasplas/reflection/static/enum.hpp index 7e53a50..906586e 100644 --- a/include/siplasplas/reflection/static/enum.hpp +++ b/include/siplasplas/reflection/static/enum.hpp @@ -71,7 +71,7 @@ class Enum /** * \brief Array type returned by values() */ - using values_array_t = const EnumType[sizeof...(Constants)]; + using values_array_t = cpp::ConstArrayView; constexpr Enum() = default; @@ -96,10 +96,10 @@ class Enum /** * \brief Returns the set of enum constants values - * \returns A const reference to a constexpr C array with the EnumType + * \returns A const array view to the enum constants values array * values */ - static constexpr const values_array_t& values() + static constexpr values_array_t values() { return ::cpp::meta::PackToArray::get(); } diff --git a/include/siplasplas/typeerasure/features/valuesemantics.hpp b/include/siplasplas/typeerasure/features/valuesemantics.hpp index 983ae66..e6ee6ae 100644 --- a/include/siplasplas/typeerasure/features/valuesemantics.hpp +++ b/include/siplasplas/typeerasure/features/valuesemantics.hpp @@ -100,40 +100,63 @@ class Constructible class CopyConstructible { public: - template - static T apply(const T& value) noexcept(concepts::CopyConstructible::no_except) + template::value> + struct Apply { - return cpp::staticIf::value>([&value](auto identity) + static T apply(const T& value) noexcept(concepts::CopyConstructible::no_except) { - return meta::type_t())>(value); - }).Else([](auto) -> T + return T{value}; + } + + static void apply(T* where, const T& value) noexcept(concepts::CopyConstructible::no_except) + { + return cpp::construct(where, value); + } + + static void apply(void* where, const void* other) noexcept(concepts::CopyConstructible::no_except) + { + return cpp::construct(where, *reinterpret_cast(other)); + } + }; + + template + struct Apply + { + static T apply(const T& ealue) noexcept(false) { throw cpp::exception( "Type '{}' is not copy constructible", ctti::type_id().name() ); - }); + } + + static void apply(T* where, const T& value) noexcept(false) + { + apply(value); + } + + static void apply(void* where, const void* other) noexcept(false) + { + apply(reinterpret_cast(where), *reinterpret_cast(other)); + } + }; + + template + static T apply(const T& value) noexcept(concepts::CopyConstructible::no_except) + { + return Apply::apply(value); } template static void apply(T* where, const T& value) noexcept(concepts::CopyConstructible::no_except) { - cpp::staticIf::value>([where, &value](auto identity) - { - cpp::construct())>>(where, value); - }).Else([](auto) -> T - { - throw cpp::exception( - "Type '{}' is not copy constructible", - ctti::type_id().name() - ); - }); + Apply::apply(where, value); } template static void apply(void* where, const void* other) noexcept(concepts::CopyConstructible::no_except) { - apply(reinterpret_cast(where), *reinterpret_cast(other)); + Apply::apply(where, other); } }; diff --git a/include/siplasplas/typeerasure/typeinfo.hpp b/include/siplasplas/typeerasure/typeinfo.hpp index f26c184..c7e4824 100644 --- a/include/siplasplas/typeerasure/typeinfo.hpp +++ b/include/siplasplas/typeerasure/typeinfo.hpp @@ -127,7 +127,7 @@ class TypeInfo : public cpp::TypeInfo */ bool isPointer() const { - return _isPointer; + return cpp::TypeInfo::isPointer(); } /** @@ -214,6 +214,16 @@ class TypeInfo : public cpp::TypeInfo } } + /** + * \brief Returns the type information of the function arguments. + * + * The behavior is undefined if the type is not a function type + */ + constexpr cpp::ConstArrayView arguments() const + { + return _functionArgs; + } + /** * \brief Returns the type information of type T */ @@ -223,6 +233,15 @@ class TypeInfo : public cpp::TypeInfo return TypeInfo{meta::identity()}; } + /** + * \brief Returns the type information of type T + */ + template + static constexpr TypeInfo get(const T&) + { + return TypeInfo::get(); + } + friend constexpr bool operator==(const TypeInfo& lhs, const TypeInfo& rhs) { return lhs._semantics == rhs._semantics; @@ -234,20 +253,32 @@ class TypeInfo : public cpp::TypeInfo } private: + struct TypeToTypeInfo + { + using value_type = TypeInfo; + + template + static constexpr TypeInfo get() + { + return TypeInfo::get(); + } + }; + template constexpr TypeInfo(meta::identity) : cpp::TypeInfo{cpp::TypeInfo::get()}, - _semantics{detail::valueSemanticsOperation}, - _isPointer{ - std::is_pointer::value && - cpp::function_kind() != cpp::FunctionKind::FREE_FUNCTION + _semantics{detail::valueSemanticsOperation>}, + _functionArgs{ + cpp::meta::SequenceToArray< + cpp::function_arguments, + TypeToTypeInfo + >::get() } - { - static_assert(alignof(T) < (1 << 16), "Alignment of T cannot be tagged in a pointer, its value overflows a 16 bit unsigned integer"); - } + {} detail::ValueSemantics _semantics; - bool _isPointer; + cpp::ConstArrayView _functionArgs; + }; } diff --git a/include/siplasplas/utility/function_traits.hpp b/include/siplasplas/utility/function_traits.hpp index 43c5f06..50db0b9 100644 --- a/include/siplasplas/utility/function_traits.hpp +++ b/include/siplasplas/utility/function_traits.hpp @@ -38,6 +38,7 @@ namespace detail template struct get_function_signature { + using args = meta::list<>; static constexpr FunctionKind kind = FunctionKind::INVALID; }; diff --git a/include/siplasplas/utility/meta.hpp b/include/siplasplas/utility/meta.hpp index aa60880..2c2ef6b 100644 --- a/include/siplasplas/utility/meta.hpp +++ b/include/siplasplas/utility/meta.hpp @@ -1,6 +1,7 @@ #ifndef SIPLASPLAS_UTILITY_META_H #define SIPLASPLAS_UTILITY_META_H +#include "array_view.hpp" #include #include @@ -170,55 +171,204 @@ namespace meta template using string = list...>; - template + struct DummyValueToType {}; + + template class SequenceToArray; - template class Seq, typename T, T... Values> - class SequenceToArray...>> + + template class Seq, typename Head, typename... Tail, typename TypeToValue> + class SequenceToArray, TypeToValue> { public: - using array_t = const T[sizeof...(Values)]; + using value_type = typename TypeToValue::value_type; + + constexpr SequenceToArray() = default; - static constexpr const array_t& get() + static constexpr const value_type& get(std::size_t i) { - return array; + return array[i]; } - static constexpr const T get(std::size_t i) + static constexpr ConstArrayView get() { - return array[i]; + return {Bounds::begin(), Bounds::size()}; + } + + struct Bounds + { + static constexpr std::size_t size() + { + return sizeof...(Tail) + 1; + } + + static constexpr const value_type* begin() + { + return array; + } + + static constexpr const value_type* end() + { + return array + size(); + } + + static constexpr const value_type* const cbegin() + { + return array; + } + + static constexpr const value_type* const cend() + { + return array + size(); + } + }; + + constexpr std::size_t size() const + { + return Bounds::size(); } - static constexpr std::size_t size() + constexpr const value_type& operator[](std::size_t i) const { - return sizeof...(Values); + return get(i); + } + + constexpr const value_type* begin() const + { + return Bounds::begin(); + } + + constexpr const value_type* end() const + { + return Bounds::end(); + } + + constexpr const value_type* const cbegin() const + { + return Bounds::cbegin(); + } + + constexpr const value_type* const cend() const + { + return Bounds::cend(); } private: - static constexpr const T array[sizeof...(Values)] = {Values...}; + static constexpr value_type array[] = { + TypeToValue::template get(), + TypeToValue::template get()... + }; }; - template - using PackToArray = SequenceToArray...>>; + template class Seq, typename Head, typename... Tail, typename TypeToValue> + constexpr typename TypeToValue::value_type SequenceToArray, TypeToValue>::array[sizeof...(Tail) + 1]; + + template class Seq, typename TypeToValue> + class SequenceToArray, TypeToValue> + { + public: + using value_type = typename TypeToValue::value_type; + + constexpr SequenceToArray() = default; + + static constexpr const value_type& get(std::size_t i) + { + return *static_cast(nullptr); + } + + struct Bounds + { + static constexpr std::size_t size() + { + return 0; + } + + static constexpr const value_type* begin() + { + return nullptr; + } + + static constexpr const value_type* end() + { + return nullptr; + } + + static constexpr const value_type* const cbegin() + { + return nullptr; + } + + static constexpr const value_type* const cend() + { + return nullptr; + } + }; + + static constexpr ConstArrayView get() + { + return {static_cast(nullptr), static_cast(0)}; + } - template class Seq, typename T, T... Values> - constexpr const T SequenceToArray...>>::array[sizeof...(Values)]; + constexpr std::size_t size() const + { + return Bounds::size(); + } + + constexpr const value_type& operator[](std::size_t i) const + { + return get(i); + } + + constexpr const value_type* begin() const + { + return Bounds::begin(); + } + + constexpr const value_type* end() const + { + return Bounds::end(); + } + + constexpr const value_type* const cbegin() const + { + return Bounds::cbegin(); + } + + constexpr const value_type* const cend() const + { + return Bounds::cend(); + } + }; + + template + struct IntegralConstantToValue + { + using value_type = T; + + template + static constexpr value_type get() + { + return IntegralConstant::value; + } + }; + + template + using PackToArray = SequenceToArray< + list...>, + IntegralConstantToValue + >; template class StringToArray; template class Seq, char... Chars> - class StringToArray...>> : public SequenceToArray..., std::integral_constant>> + class StringToArray...>> : + public PackToArray { public: static constexpr const char* c_str() { - return SequenceToArray..., std::integral_constant>>::get(); - } - - static constexpr std::size_t length() - { - return sizeof...(Chars); + return PackToArray::Bounds::begin(); } }; diff --git a/test/typeerasure/typeinfo_test.cpp b/test/typeerasure/typeinfo_test.cpp index 547e8f3..58b85d6 100644 --- a/test/typeerasure/typeinfo_test.cpp +++ b/test/typeerasure/typeinfo_test.cpp @@ -4,6 +4,11 @@ using namespace ::testing; using namespace ::cpp::typeerasure; +static_assert( + TypeInfo::get().arguments()[1] == TypeInfo::get(), + "Second param of void(int, const std::string&) is const std::string&" +); + TEST(TypeInfoTest, equalityOperator_sameTypesEqual) { EXPECT_EQ(TypeInfo::get(), TypeInfo::get());