X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fcommon%2Finline_variant.h;fp=src%2Fceph%2Fsrc%2Fcommon%2Finline_variant.h;h=bd55a59116cda06fe69cf9bef28429b7a654cdf9;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/common/inline_variant.h b/src/ceph/src/common/inline_variant.h new file mode 100644 index 0000000..bd55a59 --- /dev/null +++ b/src/ceph/src/common/inline_variant.h @@ -0,0 +1,210 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:4; indent-tabs-mode:t -*- +// vim: ts=8 sw=4 smarttab +/* + * Copied from: + * https://github.com/exclipy/inline_variant_visitor/blob/master/inline_variant.hpp + */ + +#ifndef INLINE_VARIANT_H +#define INLINE_VARIANT_H + +#include +#include +#include +#include +#include +#include + +#include "function_signature.h" + +namespace detail { + +// A metafunction class for getting the argument type from a unary function or functor type +struct function_arg_extractor +{ + // Function is either a function type like void(int const&), or a functor - eg. a class with void operator(int) + // Sets type to the argument type with the constness and referenceness stripped (eg. int) + template + struct apply + { + private: + typedef typename boost::remove_const< typename boost::remove_reference::type >::type bare_type; + typedef typename signature_of::type normalized_function_type; + typedef typename boost::function_types::function_arity::type arity; + typedef typename boost::function_types::parameter_types::type parameter_types; + typedef typename boost::function_types::result_type::type result_type; + + BOOST_STATIC_ASSERT_MSG((arity::value == 1), "make_visitor called with a non-unary function"); + + typedef typename boost::mpl::front::type parameter_type; + public: + typedef typename boost::remove_const< typename boost::remove_reference::type >::type type; + }; +}; + +struct make_pair +{ + template + struct apply { + typedef boost::mpl::pair type; + }; +}; + +// A metafunction class that asserts the second argument is in Allowed, and returns void +template +struct check_in +{ + template + struct apply + { + private: + BOOST_STATIC_ASSERT_MSG((boost::mpl::contains::type>::value), + "make_visitor called with spurious handler functions"); + public: + typedef void type; + }; +}; + +template +struct as_map +{ +private: + struct insert_helper { + template + struct apply + { + typedef typename boost::mpl::insert< + M, + P>::type type; + }; + }; +public: + typedef typename boost::mpl::fold, insert_helper>::type type; +}; + +// A functor template suitable for passing into apply_visitor. The constructor accepts the list of handler functions, +// which are then exposed through a set of operator()s +template +struct generic_visitor : boost::static_visitor, boost::noncopyable +{ +private: + typedef generic_visitor type; + + // Compute the function_map type + typedef boost::mpl::vector function_types; + typedef typename boost::mpl::transform::type arg_types; + typedef typename boost::mpl::transform< + arg_types, + boost::mpl::range_c::value>, + make_pair + >::type pair_list; + typedef typename as_map::type fmap; + + // Check that the argument types are unique + BOOST_STATIC_ASSERT_MSG((boost::mpl::size::value == boost::mpl::size::value), + "make_visitor called with non-unique argument types for handler functions"); + + // Check that there aren't any argument types not in the variant types + typedef typename boost::mpl::fold >::type dummy; + + boost::fusion::vector fvec; + + + template + Result apply_helper(const T& object, boost::mpl::true_) const { + typedef typename boost::mpl::at::type Ind; + return boost::fusion::at(fvec)(object); + } + + template + Result apply_helper(const T& object, boost::mpl::false_) const { + return Result(); + } + + BOOST_MOVABLE_BUT_NOT_COPYABLE(generic_visitor) + +public: + generic_visitor(BOOST_RV_REF(type) other) + : + fvec(boost::move(other.fvec)) + { + } + generic_visitor(Functions&&... functions) + : + fvec(std::forward(functions)...) + { + } + + template + Result operator()(const T& object) const { + typedef typename boost::mpl::has_key::type correct_key; + BOOST_STATIC_ASSERT_MSG(correct_key::value, + "make_visitor called without specifying handlers for all required types"); + return apply_helper(object, correct_key()); + } +}; + +// A metafunction class for getting the return type of a function +struct function_return_extractor +{ + template + struct apply : boost::function_types::result_type::type> + { + }; +}; + +// A metafunction class that asserts the two arguments are the same and returns the first one +struct check_same +{ + template + struct apply + { + private: + BOOST_STATIC_ASSERT_MSG((boost::is_same::value), + "make_visitor called with functions of differing return types"); + public: + typedef Type1 type; + }; +}; + +// A metafunction for getting the required generic_visitor type for the set of Functions +template +struct get_generic_visitor +{ +private: + typedef boost::mpl::vector function_types; + typedef typename boost::mpl::transform< + function_types, + boost::remove_const< boost::remove_reference > + >::type bare_function_types; + typedef typename boost::mpl::transform::type return_types; + +public: + // Set result_type to the return type of the first function + typedef typename boost::mpl::front::type result_type; + typedef generic_visitor type; + +private: + // Assert that every return type is the same as the first one + typedef typename boost::mpl::fold::type dummy; +}; + +// Accepts a set of functions and returns an object suitable for apply_visitor +template +auto make_visitor(BOOST_RV_REF(Functions)... functions) + -> typename detail::get_generic_visitor::type +{ + return typename detail::get_generic_visitor::type(boost::forward(functions)...); +} + +} + +template +auto match(Variant const& variant, BOOST_RV_REF(Functions)... functions) + -> typename detail::get_generic_visitor::result_type +{ + return boost::apply_visitor(detail::make_visitor( + boost::forward(functions)...), variant); +} + +#endif