variant

class RTTR_API variant

对github项目rttr(C++反射库)解析,链接:https://github.com/rttrorg/rttr

namespace rttr
{
class variant_associative_view;
class variant_sequential_view;
class type;
class variant;
class argument;
class instance;

namespace detail
{
    template<class T>
    RTTR_INLINE T* unsafe_variant_cast(variant* operand) RTTR_NOEXCEPT;
    template<class T>
    RTTR_INLINE const T* unsafe_variant_cast(const variant* operand) RTTR_NOEXCEPT;

    struct data_address_container;
    template<typename T>
    struct empty_type_converter;

    template<typename T, typename Tp, typename Converter = empty_type_converter<T>>
    struct variant_data_base_policy;
    struct variant_data_policy_nullptr_t;

    enum class variant_policy_operation : uint8_t;

    template<typename T, typename Decayed = decay_except_array_t<T>>
    using decay_variant_t = enable_if_t<!std::is_same<Decayed, variant>::value, Decayed>;

    using variant_policy_func = bool (*)(variant_policy_operation, const variant_data&, argument_wrapper);
}
class RTTR_API variant
{
    ...
    private:
    	friend class argument;
        friend class instance;

        template<typename T, typename Tp, typename Converter>
        friend struct detail::variant_data_base_policy;
        friend struct detail::variant_data_policy_nullptr_t;
        friend RTTR_API bool detail::variant_compare_less(const variant&, const type&, const variant&, const type&, bool& ok);
        template<class T>
        friend RTTR_INLINE T* detail::unsafe_variant_cast(variant* operand) RTTR_NOEXCEPT;


        detail::variant_data            m_data;
        detail::variant_policy_func     m_policy;
}

variant_data

namespace rttr
{
namespace detail
{

/

using variant_basic_types = type_list<bool,
                                      signed char, unsigned char, char, wchar_t,
                                      short int, unsigned short int, int, unsigned int,
                                      long int, unsigned long int, long long int,
                                      unsigned long long int, float, double, void*>;

/*!
 * This is the data storage for the \ref variant class.
 */
using variant_data = std::aligned_storage<max_sizeof_list<variant_basic_types>::value,
                                          max_alignof_list<variant_basic_types>::value>::type;

/

struct RTTR_API void_variant_type {};

} // end namespace detail
} // end namespace rttr
  • std::aligned_storage
template< std::size_t Len, 
          std::size_t Align = /*default-alignment*/ >
struct aligned_storage;
template<std::size_t Len, std::size_t Align /* 未实现默认对齐 */>
struct aligned_storage
{
    struct type
    {
        alignas(Align) unsigned char data[Len];
    };
};

std::aligned_storage对象构造完成时,即分配了长度为Len个字节的内存,且该内存满足大小为 Align 的对齐要求。

  • max_sizeof_list
template<typename... Ts>
using max_sizeof_list = std::integral_constant<std::size_t, max_sizeof_list_impl<Ts...>::value>;
  • max_alignof_list
template<typename... Ts>
using max_alignof_list = std::integral_constant<std::size_t, max_alignof_list_impl<Ts...>::value>;
  • std::integral_constant
template< class T, T v >
struct integral_constant;

传入类型T,使其成员变量成为v的数值。

  • max_alignof_list_impl
template <typename T, typename...Ts>
struct max_alignof_list_impl;

template <typename T>
struct max_alignof_list_impl<T>
{
    static RTTR_CONSTEXPR_OR_CONST size_t value = std::alignment_of<T>::value;
};

template<typename T1, typename T2, typename... U>
struct max_alignof_list_impl<T1, T2, U...>
{
    static RTTR_CONSTEXPR_OR_CONST std::size_t value = max_alignof_list_impl<
           conditional_t<std::alignment_of<T1>::value >= std::alignment_of<T2>::value, T1, T2>, U...>::value;
};

template<template<class...> class List, typename... Ts>
struct max_alignof_list_impl<List<Ts...>>
{
    static RTTR_CONSTEXPR_OR_CONST std::size_t value = max_alignof_list_impl<Ts...>::value;
};

max_alignof_list_impl模板偏特化,using max_alignof_list = std::integral_constant<std::size_t, max_alignof_list_impl<Ts…>::value>;执行哪一个?由Ts个数决定,但最终都和std::alignment_of::value相关,最终返回T类型的按照sizeof对齐的大小。

  • max_sizeof_list
template <typename T, typename...Ts>
struct max_sizeof_list_impl;

template <typename T>
struct max_sizeof_list_impl<T>
{
    static RTTR_CONSTEXPR_OR_CONST size_t value = sizeof(T);
};

template<typename T1, typename T2, typename... U>
struct max_sizeof_list_impl<T1, T2, U...>
{
    static RTTR_CONSTEXPR_OR_CONST std::size_t value = max_sizeof_list_impl< conditional_t< sizeof(T1) >= sizeof(T2),T1,T2>,U...>::value;
};

template<template<class...> class List, class... Ts>
struct max_sizeof_list_impl<List<Ts...>>
{
    static RTTR_CONSTEXPR_OR_CONST std::size_t value = max_sizeof_list_impl<Ts...>::value;
};

同理max_alignof_list_impl,和sizeof(T)相关。

  • variant_basic_types
using variant_basic_types = type_list<bool,
                                      signed char, unsigned char, char, wchar_t,
                                      short int, unsigned short int, int, unsigned int,
                                      long int, unsigned long int, long long int,
                                      unsigned long long int, float, double, void*>;
  • type_list
namespace rttr
{
template<typename...T>
struct type_list
{
    static RTTR_CONSTEXPR_OR_CONST auto size = sizeof...(T); //!< The amount of template parameters
};
} // end namespace rttr

variant_data是做什么?

using variant_data = std::aligned_storage<max_sizeof_list<variant_basic_types>::value,
                                          max_alignof_list<variant_basic_types>::value>::type;

找到type_list类模板中最大的类型大小以及最大的对齐大小,并按照此最大类型的大小分配内存并满足最大的对齐大小的对齐要求。

variant_data = alignas(max_alignof_list<variant_basic_types>::value) unsigned char data[max_sizeof_list<variant_basic_types>::value];

variant_policy_func

using variant_policy_func = bool (*)(variant_policy_operation, const variant_data&, argument_wrapper);
  • variant_policy_operation
enum class variant_policy_operation : uint8_t
{
    DESTROY,
    CLONE,
    SWAP,
    EXTRACT_WRAPPED_VALUE,
    CREATE_WRAPPED_VALUE,
    GET_VALUE,
    GET_TYPE,
    GET_PTR,
    GET_RAW_TYPE,
    GET_RAW_PTR,
    GET_ADDRESS_CONTAINER,
    IS_ASSOCIATIVE_CONTAINER,
    IS_SEQUENTIAL_CONTAINER,
    CREATE_ASSOCIATIV_VIEW,
    CREATE_SEQUENTIAL_VIEW,
    IS_VALID,
    IS_NULLPTR,
    CONVERT,
    COMPARE_EQUAL,
    COMPARE_LESS
};
  • argument_wrapper
struct argument_wrapper
{
    argument_wrapper() : m_data(nullptr) {}

    template<typename T, typename Tp = typename std::enable_if<!std::is_same<T, argument_wrapper>::value, T>::type>
    argument_wrapper(T&& data) : m_data(const_cast<void*>(reinterpret_cast<const void*>(std::addressof(data)))) {}

    template<typename T>
    T& get_value() const
    {
        using raw_type = typename std::remove_reference<T>::type;
        return (*reinterpret_cast<raw_type*>(const_cast<void *>(m_data)));
    }

    void* m_data;
};

argument_wrapper的主要作用:将T类型的数据存放进m_data并有能力获取m_data地址

class RTTR_API variant

  • RTTR_INLINE variant();

    RTTR_INLINE variant::variant()
    :   m_policy(&detail::variant_data_policy_empty::invoke)
    {
    }
    

    只是对m_policy成员初始化并没有对m_data初始化?

    • variant_data_policy_empty::invoke
    static bool invoke(variant_policy_operation op, const variant_data& src_data, argument_wrapper arg)
    
    static bool invoke(variant_policy_operation op, const variant_data& src_data, argument_wrapper arg)
    {
        switch (op)
        {
            case variant_policy_operation::DESTROY:
            case variant_policy_operation::CLONE:
            case variant_policy_operation::SWAP:
            case variant_policy_operation::EXTRACT_WRAPPED_VALUE:
            case variant_policy_operation::CREATE_WRAPPED_VALUE:
            {
                break;
            }
            case variant_policy_operation::GET_VALUE:
            {
                arg.get_value<const void*>() = nullptr;
                break;
            }
            case variant_policy_operation::GET_TYPE:
            {
                arg.get_value<type>() = get_invalid_type();
                break;
            }
            case variant_policy_operation::GET_PTR:
            {
                arg.get_value<void*>() = nullptr;
                break;
            }
            case variant_policy_operation::GET_RAW_TYPE:
            {
                arg.get_value<type>() = get_invalid_type();
                break;
            }
            case variant_policy_operation::GET_RAW_PTR:
            {
                arg.get_value<void*>() = nullptr;
                break;
            }
            case variant_policy_operation::GET_ADDRESS_CONTAINER:
            {
                data_address_container& data        = arg.get_value<data_address_container>();
    
                data.m_type                         = get_invalid_type();
                data.m_wrapped_type                 = get_invalid_type();
                data.m_data_address                 = nullptr;
                data.m_data_address_wrapped_type    = nullptr;
                break;
            }
            case variant_policy_operation::IS_ASSOCIATIVE_CONTAINER:
            {
                return false;
            }
            case variant_policy_operation::IS_SEQUENTIAL_CONTAINER:
            {
                return false;
            }
            case variant_policy_operation::CREATE_ASSOCIATIV_VIEW:
            {
                break;
            }
            case variant_policy_operation::CREATE_SEQUENTIAL_VIEW:
            {
                break;
            }
            case variant_policy_operation::IS_VALID:
            {
                return false;
            }
            case variant_policy_operation::IS_NULLPTR:
            {
                return false;
            }
            case variant_policy_operation::CONVERT:
            {
                return false;
            }
            case variant_policy_operation::COMPARE_EQUAL:
            {
                const auto& param   = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
                const variant& rhs  = std::get<1>(param);
                bool& ok            = std::get<2>(param);
                if (!rhs.is_valid())
                    ok = true;
                return ok;
            }
            case variant_policy_operation::COMPARE_LESS:
            {
                return false;
            }
        }
        return true;
    }
    

    DESTROY、CLONE、SWAP、EXTRACT_WRAPPED_VALUE、CREATE_WRAPPED_VALUE、CREATE_ASSOCIATIV_VIEW、CREATE_SEQUENTIAL_VIEW无任何操作,GET_VALUE、GET_PTR、GET_RAW_PTR将class argument_wrapper中的m_data值置nullptr,GET_TYPE、GET_RAW_TYPE获取class RTTR_API type类型的值地址(class type后续说明),GET_ADDRESS_CONTAINER:初始化struct data_address_container成员变量,IS_ASSOCIATIVE_CONTAINER、IS_SEQUENTIAL_CONTAINER、IS_VALID、IS_NULLPTR、CONVERT、COMPARE_LESS都返回false,COMPARE_EQUAL:variant有效是false反之是true,但由代码得知始终是true

由默认构造函数得知:m_policy来控制不同操作下的bool返回结果

  • ​ template<typename T, typename Tp = detail::decay_variant_t> variant(T&& val);

    template<typename T, typename Tp>
    RTTR_INLINE variant::variant(T&& val)
    :   m_policy(&detail::variant_policy<Tp>::invoke)
    {
        static_assert(std::is_copy_constructible<Tp>::value || std::is_array<Tp>::value,
                      "The given value is not copy constructible, try to add a copy constructor to the class.");
    
        detail::variant_policy<Tp>::create(std::forward<T>(val), m_data);
    }
    
    • detail::decay_variant

      template<typename T, typename Decayed = decay_except_array_t<T>>
      using decay_variant_t = enable_if_t<!std::is_same<Decayed, variant>::value, Decayed>;
      
      • decay_except_array_t

        template<typename T>
        struct decay_except_array
        {
            using Tp    = remove_reference_t<T>;
            using type  = conditional_t< std::is_function<Tp>::value,
                                         add_pointer_t<Tp>,
                                         remove_cv_t<Tp>
                                       >;
        };
        
        template<typename T>
        using decay_except_array_t = typename decay_except_array<T>::type;
        

        如何TP类型是函数,则给Tp加上指针,反之移除Tp类型的const和volatile属性。

    decay_variant_t则是Decayed和variant类型不相同时decay_variant_t = conditional_t<std: : is_function::value, add_pointer_t, remove_cv_t >.

    • variant_policy

    观察所知:struct variant_data_base_policy、struct variant_data_policy_small、struct variant_data_policy_big、struct variant_data_policy_array_small、struct variant_data_policy_array_big 、struct variant_data_policy_arithmetic、struct RTTR_API variant_data_policy_string、struct RTTR_API variant_data_policy_empty、struct RTTR_API variant_data_policy_void、struct RTTR_API variant_data_policy_nullptr_t这些函数都是根据enum variant_variant_policy_operation中的选项做出不同操作(对variant_data类型的数据和argument_wrapper类型的数据进行相关操作),具体分析函数具体作用需要针对上层调用来分析,这里具体是上层来抉择variant_policy,然后在多态中的各种variant策略中进行相关创建、析构、克隆、交换操作 。

  • RTTR_INLINE variant::~variant()
RTTR_INLINE variant::~variant()
{
   m_policy(detail::variant_policy_operation::DESTROY, m_data, detail::argument_wrapper());
}

通过m_policy调用invoke相关函数,根据detail::variant_policy_operation::DESTROY选项来对其数据进行析构。

总结:只要m_data相关数据操作都会使用到m_policy来调用variant_data_base_policy::invoke()函数来对不同策略进行选择性操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脚踏车(crush)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值