diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a405e79..641dbc30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -656,6 +656,7 @@ if (TESTS) tuple/value tuple/type typeidx + types/description types/tagged uri utf8 diff --git a/test/types/description.cpp b/test/types/description.cpp new file mode 100644 index 00000000..4f5f5620 --- /dev/null +++ b/test/types/description.cpp @@ -0,0 +1,22 @@ +#include "tap.hpp" +#include "types/description.hpp" + + +/////////////////////////////////////////////////////////////////////////////// +int main () +{ + cruft::TAP::logger tap; + + tap.expect_eq ( + cruft::types::make_description (), + cruft::types::description { + .category = cruft::types::category::SIGNED, + .width = sizeof (int), + .arity = 1, + .alignment = alignof (int) + }, + "description: int" + ); + + return tap.status (); +} \ No newline at end of file diff --git a/types/description.cpp b/types/description.cpp index c2e4d953..3b1fa8c2 100644 --- a/types/description.cpp +++ b/types/description.cpp @@ -30,5 +30,9 @@ cruft::types::operator<< (std::ostream &os, cruft::types::category val) std::ostream& cruft::types::operator<< (std::ostream &os, cruft::types::description val) { - return os << "{ category: " << val.category << ", width: " << val.width << " }"; + return os << "{ category: " << val.category + << ", width: " << val.width + << ", arity: " << val.arity + << ", alignment: " << val.alignment + << " }"; } diff --git a/types/description.hpp b/types/description.hpp index 29900cda..7a852883 100644 --- a/types/description.hpp +++ b/types/description.hpp @@ -19,7 +19,36 @@ namespace cruft::types { + /////////////////////////////////////////////////////////////////////////// + /// Computes the number of elements of a scalar (ie, 1), or of statically + /// sized vector type + template + struct arity_trait { }; + + //------------------------------------------------------------------------- + // void arity is explicitly zero. + template <> + struct arity_trait : public std::integer_sequence { }; + + + //------------------------------------------------------------------------- + // All basic types are unit arity (except for void which is zero). + template + struct arity_trait< + T, + std::enable_if_t> + > : public std::integral_constant< + std::size_t, 1u + > { }; + + + //------------------------------------------------------------------------- + template + constexpr auto arity_v = arity_trait::value; + + + /////////////////////////////////////////////////////////////////////////// enum class category { NONE, UNSIGNED, @@ -27,20 +56,36 @@ namespace cruft::types { REAL, }; - //------------------------------------------------------------------------- + + ///------------------------------------------------------------------------ + /// A description of the type that makes up a scalar or vector type. + /// + /// A vector3f would be { REAL, sizeof(float), 3 }; struct description { /// The signed, realness, or voidness of the type. enum category category; /// The number of bytes for an individual instance of this type. std::size_t width; + + /// The number of variables that make up an instance. + std::size_t arity; + + std::size_t alignment; + + /// Returns the number of bytes required to store this type. + constexpr std::size_t size (void) const noexcept { return width * arity; } }; + + //------------------------------------------------------------------------- constexpr bool operator== (description const &a, description const &b) noexcept { - return a.category == b.category && - a.width == b.width; + return a.category == b.category && + a.width == b.width && + a.arity == b.arity && + a.alignment == b.alignment; } @@ -72,13 +117,17 @@ namespace cruft::types { { if constexpr (std::is_void_v) { return { - .category = category::NONE, - .width = 0, + .category = category::NONE, + .width = 0, + .arity = 1, + .alignment = 0, }; } else { return { .category = category_traits_v, - .width = sizeof (T) + .width = sizeof (T), + .arity = arity_v, + .alignment = alignof (T) }; } }