/* * 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 2015-2017 Danny Robson */ #pragma once #include #include #include namespace cruft::introspection { /////////////////////////////////////////////////////////////////////////// /// Describes a single member variable in a type availabe for introspection /// /// K: target class /// R: member type /// M: pointer-to-member template < class K, typename R, R K::*M > struct field { typedef K klass; typedef R type; static const std::string name; static const R& get (const K &k) { return k.*M; } static R& get ( K &k) { return k.*M; } static R& get ( K &&) = delete; }; /////////////////////////////////////////////////////////////////////////// /// Holds the fields of a type available for introspection /// /// Specialise the following type struct with a 'fields' tuple of the /// members that should be accessed like below: /// /// struct foo { int a; int b; }; /// /// template <> struct type /// { /// typedef std::tuple< /// field, /// field /// > fields; /// }; /// /// template <> const std::string field::name = "a"; /// template <> const std::string field::name = "b"; template struct type { }; /////////////////////////////////////////////////////////////////////////// /// traits class which converts an introspected type to a tuple /// /// K: target class template struct type_tuple; template < typename ...T > struct type_tuple< std::tuple > { typedef std::tuple type; }; template < typename K, typename I = typename std::make_index_sequence< std::tuple_size< typename type::fields >::value > > struct _type_tuple; template < typename K, size_t ...I > struct _type_tuple < K, std::index_sequence > { typedef std::tuple< typename std::tuple_element< I, typename type::fields >::type::type... > type; }; template < typename K > struct type_tuple { typedef typename _type_tuple::type type; }; /////////////////////////////////////////////////////////////////////////// namespace detail { template < typename K, typename I = typename std::make_index_sequence< std::tuple_size< typename type::fields >::value > > struct _as_tuple; template < typename K, size_t ...I > struct _as_tuple < K, std::index_sequence > { static typename type_tuple::type make (const K &k) { return std::make_tuple ( std::tuple_element::fields>::type::get (k)... ); } static auto make (K&&) = delete; }; } /// Convert an introspection capable class instance into a tuple instance /// /// K: source class template auto as_tuple (const K &k) { return detail::_as_tuple::make (k); } template auto as_tuple (K &_k) { const K &k = _k; return as_tuple (k); } template auto as_tuple (K&&) = delete; }