From 28e0a1afea512cba18a639804a1b3e8f172e6e52 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Sat, 16 Mar 2019 18:19:12 +1100 Subject: [PATCH] types/description: add visit dispatcher for descriptions --- types/description.hpp | 95 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/types/description.hpp b/types/description.hpp index 40ed8c31..c3d015ac 100644 --- a/types/description.hpp +++ b/types/description.hpp @@ -9,9 +9,14 @@ #pragma once #include "../std.hpp" +#include "../types.hpp" +#include "../debug.hpp" #include #include +#include +#include + namespace cruft::types { //------------------------------------------------------------------------- @@ -24,7 +29,10 @@ namespace cruft::types { //------------------------------------------------------------------------- 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; }; @@ -60,6 +68,93 @@ namespace cruft::types { .width = sizeof (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 + decltype(auto) + visit (description const &descriminator, FunctionT &&func, Args&&...args) + { + switch (descriminator.category) { + case category ::NONE: + return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + + case category::REAL: + switch (descriminator.width) { + case 4: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + case 8: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + default: + throw std::invalid_argument ("Unsupported floating point width"); + } + + case category::SIGNED: + switch (descriminator.width) { + case 1: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + case 2: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + case 4: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + case 8: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + default: + throw std::invalid_argument ("Unsupported unsigned width"); + } + + case category::UNSIGNED: + switch (descriminator.width) { + case 1: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + case 2: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + case 4: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + case 8: return std::invoke ( + std::forward (func), + std::forward (args)..., + type_tag {} + ); + } + } + + unhandled (descriminator.category); + } } #include