diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp index 45e781b..bb21416 100644 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -10,6 +10,8 @@ * **/ #pragma once + +#include #include #include #include @@ -176,6 +178,34 @@ struct type_info<> { } // namespace impl +template +std::vector> init_wrappers() +{ + return std::vector>(); +} + +template +std::vector> init_wrappers() +{ + std::vector> result = init_wrappers(); + result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); + return result; +} + +template +std::vector> init_const_wrappers() +{ + return std::vector>(); +} + +template +std::vector> init_const_wrappers() +{ + std::vector> result = init_const_wrappers(); + result.insert( result.begin(), [] ( Visitor& v, Data d ) { return v( *reinterpret_cast( d ) ); } ); + return result; +} + template class static_variant { static_assert(impl::type_info::no_reference_types, "Reference types are not permitted in static_variant."); @@ -308,32 +338,54 @@ public: } template typename visitor::result_type visit(visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (void*) storage ); } template typename visitor::result_type visit(const visitor& v) { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (void*) storage ); } template typename visitor::result_type visit(visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (const void*) storage ); } template typename visitor::result_type visit(const visitor& v)const { - return impl::storage_ops<0, Types...>::apply(_tag, storage, v); + return visit( _tag, v, (const void*) storage ); } - template - static typename visitor::result_type visit(visitor& v) { - return impl::storage_ops<0, Types...>::apply((const tag_type)w, (const void*)nullptr, v); + template + static typename visitor::result_type visit( tag_type tag, visitor& v, void* data ) + { + static std::vector> wrappers = init_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); } - template - static typename visitor::result_type visit(const visitor& v) { - return impl::storage_ops<0, Types...>::apply((const tag_type)w, (const void*)nullptr, v); + template + static typename visitor::result_type visit( tag_type tag, const visitor& v, void* data ) + { + static std::vector> wrappers = init_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); + } + + template + static typename visitor::result_type visit( tag_type tag, visitor& v, const void* data ) + { + static std::vector> wrappers = init_const_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); + } + + template + static typename visitor::result_type visit( tag_type tag, const visitor& v, const void* data ) + { + static std::vector> wrappers = init_const_wrappers(); + FC_ASSERT( tag < count(), "Unsupported type ${tag}!", ("tag",tag) ); + return wrappers[tag]( v, data ); } static int count() { return impl::type_info::count; }