types/description: add initial enum support
This commit is contained in:
parent
d3f23ed754
commit
41edd3cebe
@ -486,6 +486,7 @@ list (
|
|||||||
types/comparator.hpp
|
types/comparator.hpp
|
||||||
types/description.cpp
|
types/description.cpp
|
||||||
types/description.hpp
|
types/description.hpp
|
||||||
|
types/dispatch.hpp
|
||||||
types/string.cpp
|
types/string.cpp
|
||||||
types/string.hpp
|
types/string.hpp
|
||||||
types/tagged.hpp
|
types/tagged.hpp
|
||||||
|
@ -257,4 +257,15 @@ namespace cruft::types {
|
|||||||
> : public category_traits<
|
> : public category_traits<
|
||||||
::cruft::value_trait_t<CoordT>
|
::cruft::value_trait_t<CoordT>
|
||||||
> { };
|
> { };
|
||||||
|
|
||||||
|
|
||||||
|
template <typename CoordT>
|
||||||
|
struct signedness_traits<
|
||||||
|
CoordT,
|
||||||
|
std::enable_if_t<
|
||||||
|
::cruft::is_coord_v<CoordT>
|
||||||
|
>
|
||||||
|
> : public signedness_traits<
|
||||||
|
::cruft::value_trait_t<CoordT>
|
||||||
|
> { };
|
||||||
}
|
}
|
||||||
|
@ -137,8 +137,7 @@ namespace cruft::types {
|
|||||||
template <typename TagT, typename ValueT>
|
template <typename TagT, typename ValueT>
|
||||||
struct arity_trait<
|
struct arity_trait<
|
||||||
::cruft::strongdef::index<TagT, ValueT>
|
::cruft::strongdef::index<TagT, ValueT>
|
||||||
> :
|
> : public arity_trait<ValueT>
|
||||||
arity_trait<ValueT>
|
|
||||||
{ ; };
|
{ ; };
|
||||||
|
|
||||||
|
|
||||||
@ -148,4 +147,11 @@ namespace cruft::types {
|
|||||||
> :
|
> :
|
||||||
public category_traits<ValueT>
|
public category_traits<ValueT>
|
||||||
{};
|
{};
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename TagT, typename ValueT>
|
||||||
|
struct signedness_traits<
|
||||||
|
::cruft::strongdef::index<TagT,ValueT>
|
||||||
|
> : public signedness_traits<ValueT>
|
||||||
|
{ ; };
|
||||||
|
};
|
||||||
|
@ -1,5 +1,28 @@
|
|||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
#include "types/description.hpp"
|
#include "types/description.hpp"
|
||||||
|
#include "types/dispatch.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
enum an_enum_type { AN_ENUM_VALUE };
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
struct does_enum_match {
|
||||||
|
template <typename TagT>
|
||||||
|
bool operator() (cruft::type_tag<TagT> const&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename UnderlyingT>
|
||||||
|
bool operator() (cruft::type_tag<cruft::unknown_enum_tag<UnderlyingT>> const &tag)
|
||||||
|
{
|
||||||
|
auto const expected = cruft::types::make_description<an_enum_type> ();
|
||||||
|
return expected == tag.desc;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -10,13 +33,34 @@ int main ()
|
|||||||
tap.expect_eq (
|
tap.expect_eq (
|
||||||
cruft::types::make_description<int> (),
|
cruft::types::make_description<int> (),
|
||||||
cruft::types::description {
|
cruft::types::description {
|
||||||
.category = cruft::types::category::SIGNED,
|
.category = cruft::types::category::INTEGER,
|
||||||
|
.signedness = true,
|
||||||
.width = sizeof (int),
|
.width = sizeof (int),
|
||||||
.arity = 1,
|
.arity = 1,
|
||||||
.alignment = alignof (int)
|
.alignment = alignof (int),
|
||||||
|
.index = cruft::typeidx<int> (),
|
||||||
},
|
},
|
||||||
"description: int"
|
"description: int"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
tap.expect_neq (
|
||||||
|
cruft::types::make_description<i16> (),
|
||||||
|
cruft::types::make_description<u16> (),
|
||||||
|
"different signedness is unequal"
|
||||||
|
);
|
||||||
|
|
||||||
|
tap.expect_eq (
|
||||||
|
cruft::types::make_description<an_enum_type> ().category,
|
||||||
|
cruft::types::category::ENUM,
|
||||||
|
"enums are described as such"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
auto const enum_type_descriptor = cruft::types::make_description<an_enum_type> ();
|
||||||
|
tap.expect (
|
||||||
|
cruft::types::visit (enum_type_descriptor, does_enum_match {}),
|
||||||
|
"enum type descriptor dispatches correctly"
|
||||||
|
);
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
}
|
}
|
40
types.hpp
40
types.hpp
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "types/description.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -70,7 +72,36 @@ first (T a, Args&& ...b)
|
|||||||
|
|
||||||
|
|
||||||
namespace cruft {
|
namespace cruft {
|
||||||
///------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
/// A tag type that is used when type_tag dispatching descriptions that
|
||||||
|
/// claim to be enums. The underlying type can be recovered from the 'type'
|
||||||
|
/// typedef of this class.
|
||||||
|
template <typename UnderlyingT>
|
||||||
|
struct unknown_enum_tag {
|
||||||
|
using type = UnderlyingT;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <typename ValueT>
|
||||||
|
struct is_unknown_enum_tag :
|
||||||
|
public std::false_type {};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <
|
||||||
|
typename UnderlyingT
|
||||||
|
> struct is_unknown_enum_tag<
|
||||||
|
unknown_enum_tag<UnderlyingT>
|
||||||
|
>: public std::true_type {};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <typename ValueT>
|
||||||
|
constexpr auto is_unknown_enum_tag_v = is_unknown_enum_tag<ValueT>::value;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
/// represents a type as a POD struct (but is statically recoverable via
|
/// represents a type as a POD struct (but is statically recoverable via
|
||||||
/// the 'type' member).
|
/// the 'type' member).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -80,6 +111,13 @@ namespace cruft {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <typename UnderlyingT>
|
||||||
|
struct type_tag<unknown_enum_tag<UnderlyingT>> {
|
||||||
|
cruft::types::description desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///------------------------------------------------------------------------
|
||||||
/// count the number of parameters we are given. useful for counting
|
/// count the number of parameters we are given. useful for counting
|
||||||
/// arguments in variadic macros (ie, sizeof... (__VA_ARGS__))
|
/// arguments in variadic macros (ie, sizeof... (__VA_ARGS__))
|
||||||
|
@ -17,10 +17,10 @@ cruft::types::operator<< (std::ostream &os, cruft::types::category val)
|
|||||||
{
|
{
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case category::NONE: return os << "NONE";
|
case category::NONE: return os << "NONE";
|
||||||
case category::UNSIGNED: return os << "UNSIGNED";
|
case category::INTEGER: return os << "INTEGER";
|
||||||
case category::SIGNED: return os << "SIGNED";
|
|
||||||
case category::REAL: return os << "REAL";
|
case category::REAL: return os << "REAL";
|
||||||
case category::BOOL: return os << "BOOL";
|
case category::BOOL: return os << "BOOL";
|
||||||
|
case category::ENUM: return os << "ENUM";
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable ();
|
unreachable ();
|
||||||
@ -32,9 +32,11 @@ std::ostream&
|
|||||||
cruft::types::operator<< (std::ostream &os, cruft::types::description val)
|
cruft::types::operator<< (std::ostream &os, cruft::types::description val)
|
||||||
{
|
{
|
||||||
return os << "{ category: " << val.category
|
return os << "{ category: " << val.category
|
||||||
|
<< ", signedness: " << val.signedness
|
||||||
<< ", width: " << val.width
|
<< ", width: " << val.width
|
||||||
<< ", arity: " << val.arity
|
<< ", arity: " << val.arity
|
||||||
<< ", alignment: " << val.alignment
|
<< ", alignment: " << val.alignment
|
||||||
|
<< ", index: " << val.index
|
||||||
<< " }";
|
<< " }";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,10 +60,10 @@ cruft::debug::validator<cruft::types::description>::is_valid (
|
|||||||
switch (val.category) {
|
switch (val.category) {
|
||||||
// Ensure types that look fundamental might have a chance of being
|
// Ensure types that look fundamental might have a chance of being
|
||||||
// represented in hardware.
|
// represented in hardware.
|
||||||
case cruft::types::category::UNSIGNED:
|
case cruft::types::category::INTEGER:
|
||||||
case cruft::types::category::SIGNED:
|
|
||||||
case cruft::types::category::REAL:
|
case cruft::types::category::REAL:
|
||||||
case cruft::types::category::BOOL:
|
case cruft::types::category::BOOL:
|
||||||
|
case cruft::types::category::ENUM:
|
||||||
// Most numbers are only realistic if they're powers of two; it's not
|
// Most numbers are only realistic if they're powers of two; it's not
|
||||||
// a requirement, it's just stupid suspicious.
|
// a requirement, it's just stupid suspicious.
|
||||||
//
|
//
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* Copyright 2018 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2018-2019 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../std.hpp"
|
#include "../std.hpp"
|
||||||
#include "../types.hpp"
|
|
||||||
#include "../debug/panic.hpp"
|
#include "../debug/panic.hpp"
|
||||||
|
#include "../typeidx.hpp"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@ -62,10 +62,10 @@ namespace cruft::types {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
enum class category {
|
enum class category {
|
||||||
NONE,
|
NONE,
|
||||||
UNSIGNED,
|
INTEGER,
|
||||||
SIGNED,
|
|
||||||
REAL,
|
REAL,
|
||||||
BOOL,
|
BOOL,
|
||||||
|
ENUM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -78,9 +78,18 @@ namespace cruft::types {
|
|||||||
/// that confuses total byte size, element byte size, and arity.
|
/// that confuses total byte size, element byte size, and arity.
|
||||||
/// Instead: use the bytes member function, or the arity member variable.
|
/// Instead: use the bytes member function, or the arity member variable.
|
||||||
struct description {
|
struct description {
|
||||||
/// The signed, realness, or voidness of the type.
|
/// The fundamental nature of the type; is it integral, real, bool, etc.
|
||||||
enum category category;
|
enum category category;
|
||||||
|
|
||||||
|
/// Is the type considered to be signed?
|
||||||
|
///
|
||||||
|
/// For some types, like void, this does not make sense. In this case
|
||||||
|
/// the value must be false.
|
||||||
|
///
|
||||||
|
/// For other types this value will almost certainly be one value in a
|
||||||
|
/// realistic system; eg, signed floating point numbers.
|
||||||
|
bool signedness;
|
||||||
|
|
||||||
/// The number of bytes for an individual instance of this type.
|
/// The number of bytes for an individual instance of this type.
|
||||||
std::size_t width;
|
std::size_t width;
|
||||||
|
|
||||||
@ -89,6 +98,10 @@ namespace cruft::types {
|
|||||||
|
|
||||||
std::size_t alignment;
|
std::size_t alignment;
|
||||||
|
|
||||||
|
/// The value from typeidx for the constructed type (if it is known
|
||||||
|
/// and has been registered), otherwise 0.
|
||||||
|
int index;
|
||||||
|
|
||||||
/// Returns the number of bytes required to store this type.
|
/// Returns the number of bytes required to store this type.
|
||||||
constexpr std::size_t
|
constexpr std::size_t
|
||||||
bytes (void) const noexcept
|
bytes (void) const noexcept
|
||||||
@ -103,9 +116,11 @@ namespace cruft::types {
|
|||||||
operator== (description const &a, description const &b) noexcept
|
operator== (description const &a, description const &b) noexcept
|
||||||
{
|
{
|
||||||
return a.category == b.category &&
|
return a.category == b.category &&
|
||||||
|
a.signedness == b.signedness &&
|
||||||
a.width == b.width &&
|
a.width == b.width &&
|
||||||
a.arity == b.arity &&
|
a.arity == b.arity &&
|
||||||
a.alignment == b.alignment;
|
a.alignment == b.alignment &&
|
||||||
|
(a.index == 0 || b.index == 0 || a.index == b.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -121,15 +136,15 @@ namespace cruft::types {
|
|||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct category_traits;
|
struct category_traits;
|
||||||
|
|
||||||
template <> struct category_traits<u08> : public std::integral_constant<category,category::UNSIGNED> {};
|
template <> struct category_traits<u08> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
template <> struct category_traits<u16> : public std::integral_constant<category,category::UNSIGNED> {};
|
template <> struct category_traits<u16> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
template <> struct category_traits<u32> : public std::integral_constant<category,category::UNSIGNED> {};
|
template <> struct category_traits<u32> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
template <> struct category_traits<u64> : public std::integral_constant<category,category::UNSIGNED> {};
|
template <> struct category_traits<u64> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
|
|
||||||
template <> struct category_traits<i08> : public std::integral_constant<category,category::SIGNED> {};
|
template <> struct category_traits<i08> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
template <> struct category_traits<i16> : public std::integral_constant<category,category::SIGNED> {};
|
template <> struct category_traits<i16> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
template <> struct category_traits<i32> : public std::integral_constant<category,category::SIGNED> {};
|
template <> struct category_traits<i32> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
template <> struct category_traits<i64> : public std::integral_constant<category,category::SIGNED> {};
|
template <> struct category_traits<i64> : public std::integral_constant<category,category::INTEGER> {};
|
||||||
|
|
||||||
template <> struct category_traits<f32> : public std::integral_constant<category,category::REAL> {};
|
template <> struct category_traits<f32> : public std::integral_constant<category,category::REAL> {};
|
||||||
template <> struct category_traits<f64> : public std::integral_constant<category,category::REAL> {};
|
template <> struct category_traits<f64> : public std::integral_constant<category,category::REAL> {};
|
||||||
@ -143,7 +158,7 @@ namespace cruft::types {
|
|||||||
std::enable_if_t<
|
std::enable_if_t<
|
||||||
std::is_enum_v<EnumT>
|
std::is_enum_v<EnumT>
|
||||||
>
|
>
|
||||||
> : public category_traits<std::underlying_type_t<EnumT>>
|
> : public std::integral_constant<category,category::ENUM>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
|
|
||||||
@ -152,122 +167,64 @@ namespace cruft::types {
|
|||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
template <typename, typename = void>
|
||||||
|
struct signedness_traits;
|
||||||
|
|
||||||
|
template <> struct signedness_traits<u08> : public std::false_type {};
|
||||||
|
template <> struct signedness_traits<u16> : public std::false_type {};
|
||||||
|
template <> struct signedness_traits<u32> : public std::false_type {};
|
||||||
|
template <> struct signedness_traits<u64> : public std::false_type {};
|
||||||
|
|
||||||
|
template <> struct signedness_traits<i08> : public std::true_type {};
|
||||||
|
template <> struct signedness_traits<i16> : public std::true_type {};
|
||||||
|
template <> struct signedness_traits<i32> : public std::true_type {};
|
||||||
|
template <> struct signedness_traits<i64> : public std::true_type {};
|
||||||
|
|
||||||
|
template <> struct signedness_traits<f32> : public std::true_type {};
|
||||||
|
template <> struct signedness_traits<f64> : public std::true_type {};
|
||||||
|
|
||||||
|
template <> struct signedness_traits<bool> : public std::false_type {};
|
||||||
|
|
||||||
|
template <typename EnumT>
|
||||||
|
struct signedness_traits<
|
||||||
|
EnumT,
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_enum_v<EnumT>
|
||||||
|
>
|
||||||
|
>: public signedness_traits<std::underlying_type_t<EnumT>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr description
|
constexpr auto signedness_traits_v = signedness_traits<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <typename T>
|
||||||
|
description
|
||||||
make_description (void) noexcept
|
make_description (void) noexcept
|
||||||
{
|
{
|
||||||
if constexpr (std::is_void_v<T>) {
|
if constexpr (std::is_void_v<T>) {
|
||||||
return {
|
return {
|
||||||
.category = category::NONE,
|
.category = category::NONE,
|
||||||
|
.signedness = false,
|
||||||
.width = 0,
|
.width = 0,
|
||||||
.arity = 1,
|
.arity = 1,
|
||||||
.alignment = 0,
|
.alignment = 0,
|
||||||
|
.index = cruft::typeidx<T> (),
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
.category = category_traits_v<T>,
|
.category = category_traits_v<T>,
|
||||||
|
.signedness = signedness_traits_v<T>,
|
||||||
.width = sizeof (T),
|
.width = sizeof (T),
|
||||||
.arity = arity_v<T>,
|
.arity = arity_v<T>,
|
||||||
.alignment = alignof (T)
|
.alignment = alignof (T),
|
||||||
|
.index = cruft::typeidx<T> (),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Call a functor with the supplied arguments and a type_tag for the
|
|
||||||
/// described native type.
|
|
||||||
///
|
|
||||||
/// If the type does not exist then throw and invalid_argument exception.
|
|
||||||
template <typename FunctionT, typename ...Args>
|
|
||||||
decltype(auto)
|
|
||||||
visit (description const &descriminator, FunctionT &&func, Args&&...args)
|
|
||||||
{
|
|
||||||
switch (descriminator.category) {
|
|
||||||
case category ::NONE:
|
|
||||||
return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<void> {}
|
|
||||||
);
|
|
||||||
|
|
||||||
case category::REAL:
|
|
||||||
switch (descriminator.width) {
|
|
||||||
case 4: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<f32> {}
|
|
||||||
);
|
|
||||||
case 8: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<f64> {}
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument ("Unsupported floating point width");
|
|
||||||
}
|
|
||||||
|
|
||||||
case category::SIGNED:
|
|
||||||
switch (descriminator.width) {
|
|
||||||
case 1: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<i08> {}
|
|
||||||
);
|
|
||||||
case 2: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<i16> {}
|
|
||||||
);
|
|
||||||
case 4: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<i32> {}
|
|
||||||
);
|
|
||||||
case 8: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<i64> {}
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument ("Unsupported unsigned width");
|
|
||||||
}
|
|
||||||
|
|
||||||
case category::UNSIGNED:
|
|
||||||
switch (descriminator.width) {
|
|
||||||
case 1: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<u08> {}
|
|
||||||
);
|
|
||||||
case 2: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<u16> {}
|
|
||||||
);
|
|
||||||
case 4: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<u32> {}
|
|
||||||
);
|
|
||||||
case 8: return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<u64> {}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
case category::BOOL:
|
|
||||||
return std::invoke (
|
|
||||||
std::forward<FunctionT> (func),
|
|
||||||
std::forward<Args> (args)...,
|
|
||||||
type_tag<bool> {}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
unhandled (descriminator.category);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
namespace cruft::types {
|
namespace cruft::types {
|
||||||
std::ostream& operator<< (std::ostream&, category);
|
std::ostream& operator<< (std::ostream&, category);
|
||||||
|
89
types/dispatch.hpp
Normal file
89
types/dispatch.hpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* Copyright 2018-2019 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "description.hpp"
|
||||||
|
#include "../types.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace cruft::types {
|
||||||
|
/// Call a functor with the supplied arguments and a type_tag for the
|
||||||
|
/// described native type.
|
||||||
|
///
|
||||||
|
/// If the type does not exist then throw and invalid_argument exception.
|
||||||
|
///
|
||||||
|
/// We split the calls into two here so that there's no possibility of
|
||||||
|
/// recursion (which will blow up the compiler) when we handle the
|
||||||
|
/// dispatch of enums.
|
||||||
|
template <typename FunctionT, typename ...Args>
|
||||||
|
decltype(auto)
|
||||||
|
visit (description const &descriminator, FunctionT &&func, Args&&...args)
|
||||||
|
{
|
||||||
|
#define INVOKE(KLASS) \
|
||||||
|
return std::invoke( \
|
||||||
|
std::forward<FunctionT> (func), \
|
||||||
|
std::forward<Args> (args)..., \
|
||||||
|
type_tag<KLASS> {} \
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (descriminator.category) {
|
||||||
|
case category ::NONE: INVOKE(void)
|
||||||
|
case category::REAL:
|
||||||
|
switch (descriminator.width) {
|
||||||
|
case 4: INVOKE(f32)
|
||||||
|
case 8: INVOKE(f64)
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument ("Unsupported floating point width");
|
||||||
|
}
|
||||||
|
|
||||||
|
case category::BOOL: INVOKE(bool)
|
||||||
|
|
||||||
|
case category::ENUM: {
|
||||||
|
if (descriminator.signedness) {
|
||||||
|
switch (descriminator.width) {
|
||||||
|
case 1: INVOKE(unknown_enum_tag<i08>)
|
||||||
|
case 2: INVOKE(unknown_enum_tag<i16>)
|
||||||
|
case 3: INVOKE(unknown_enum_tag<i32>)
|
||||||
|
case 4: INVOKE(unknown_enum_tag<i64>)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (descriminator.width) {
|
||||||
|
case 1: INVOKE(unknown_enum_tag<u08>)
|
||||||
|
case 2: INVOKE(unknown_enum_tag<u16>)
|
||||||
|
case 3: INVOKE(unknown_enum_tag<u32>)
|
||||||
|
case 4: INVOKE(unknown_enum_tag<u64>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case category::INTEGER:
|
||||||
|
CHECK_EQ (category::INTEGER, descriminator.category);
|
||||||
|
|
||||||
|
if (descriminator.signedness) {
|
||||||
|
switch (descriminator.width) {
|
||||||
|
case 1: INVOKE(i08)
|
||||||
|
case 2: INVOKE(i16)
|
||||||
|
case 3: INVOKE(i32)
|
||||||
|
case 4: INVOKE(i64)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (descriminator.width) {
|
||||||
|
case 1: INVOKE(u08)
|
||||||
|
case 2: INVOKE(u16)
|
||||||
|
case 3: INVOKE(u32)
|
||||||
|
case 4: INVOKE(u64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unhandled (descriminator.category);
|
||||||
|
}
|
||||||
|
|
||||||
|
unhandled (descriminator.category);
|
||||||
|
#undef INVOKE
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user