原创文章,未经许可,禁止转载!

5 variant policy代码解读1

  • rttr/detail/variant/variant_data_policy.h

1. variant_data_policy_empty

variant_data_policy_empty用作构造空的variant的时候,也就是variant构造时不传参数时m_policy使用的默认policy,因此这个policy也没有太多的可操作的部分,基本上取值就是返回nullptr,取类型拿到的就是invalid_type,也没有提供create的操作,因此这个policy不做详解。

2. variant_data_policy_void

variant_data_policy_void用于操控void类型的变量,对于void类型来说,大多数的操作都有没有意义的,比如create,clone,swap,接下来只解读有意义的操作,具体的源代码可以去查阅 variant_data_policy_void::invoke

// 对于void类型,返回值就是nullptr
case variant_policy_operation::GET_VALUE:
{
    arg.get_value<const void*>() = nullptr;
    break;
}
// void类型的type实例就是type::get<void>()
case variant_policy_operation::GET_TYPE:
{
    arg.get_value<type>() = type::get<void>();
    break;
}
// void类型的指针就是nullptr
case variant_policy_operation::GET_PTR:
{
    arg.get_value<void*>() = nullptr;
}
// void类型不会被包装,所以type实例也是type::get<void>()
case variant_policy_operation::GET_RAW_TYPE:
{
    arg.get_value<type>() = type::get<void>();
    break;
}
// 没有被包装,自然裸指针也是nullptr
case variant_policy_operation::GET_RAW_PTR:
{
    arg.get_value<void*>() = nullptr;
    break;
}
// 这里传续的arg必须是用argment_wrapped包装过的data_address_container
// 通过把data_address_container解出来,为其赋值
// type和wrapped_type自然都是void的type实例
// void类型也不存任何数据,所以address都赋予nullptr在通过arg传回给调用者
case variant_policy_operation::GET_ADDRESS_CONTAINER:
{
    data_address_container& data        = arg.get_value<data_address_container>();

    data.m_type                         = type::get<void>();
    data.m_wrapped_type                 = type::get<void>();
    data.m_data_address                 = nullptr;
    data.m_data_address_wrapped_type    = nullptr;
    break;
}
// 判断传入参数的type和本身是否一样,这里传入的arg是一个tuple,
// 第0个元素就是需要比较的类型,第1个元素是返回值,
// 通过比较第0个元素是否为void类型,将返回结果写入ok返回
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_type<void>())
        ok = true;
    return ok;
}

3. variant_data_policy_nullptr_t

这个policy是用来操作std::nullptr_t类型的。首先,policy_nullptr_t有一些操作需要经常使用,比如get_value,因此将这些操作抽取成了函数以供调用。

// 取值过程是强转variant_data至std::nullptr_t类型,这里又有了之前的一个操作,
// 就是实参用了const,然后通过const_cast统一去掉const约束
static RTTR_INLINE std::nullptr_t& get_value(const variant_data& data)
{
    return reinterpret_cast<std::nullptr_t&>(const_cast<variant_data&>(data));
}
// 调用nullptr_t对象的析构,这里作者有一段表述就是要把析构放在destroy函数里调用
// 是因为mingw 会有问题,我没有拿mingw测试过,所以也不是很清楚有什么问题
static RTTR_INLINE void destroy(std::nullptr_t& value)
{
    // for unknown reason we have to fully qualify the dtor call here;
    // otherwise mingw has reports a problems here: 
    // "request for member 'nullptr_t' in non-class type 'std::nullptr_t'"
    value.std::nullptr_t::~nullptr_t();
}
// 这里直接把variant_data的空间上placement new一个std::nullptr_t的对象,
// 并且把value作为初始化对象。因为variant_data就是一段空间,
// 而std::nullptr_t肯定可以放入这块空间。
static RTTR_INLINE void clone(const std::nullptr_t& value, variant_data& dest)
{
    new (&dest) std::nullptr_t(value);
}
// 这里直接在目标空间placement new一个nullptr_t,然后销毁原来的value。
static RTTR_INLINE void swap(std::nullptr_t& value, variant_data& dest)
{
    new (&dest) std::nullptr_t(value);
    destroy(value);
}

invoke的处理抽取了有意义的部分如下:
// 销毁一个nullptr_t的variant_data
case variant_policy_operation::DESTROY:
{
    destroy(get_value(src_data));
    break;
}
// 复制一个nullptr_t的variant_data
case variant_policy_operation::CLONE:
{
    clone(get_value(src_data), arg.get_value<variant_data>());
    break;
}
// 交换variant_data,这里作者把src_data析构了,没看懂什么意思
case variant_policy_operation::SWAP:
{
    swap(get_value(src_data), arg.get_value<variant_data>());
    break;
}
// 取值
case variant_policy_operation::GET_VALUE:
{
    arg.get_value<const void*>() = &get_value(src_data);
    break;
}
// 获取type实例,因为policy_nullptr_t只有std::nullptr_t一种类型,
// 直接返回std::nullptr_t的type实例即可
case variant_policy_operation::GET_TYPE:
{
    arg.get_value<type>() = type::get<std::nullptr_t>();
    break;
}
// 将variant_data的地址强转成void*,然后通过赋值arg返回给调用方
case variant_policy_operation::GET_PTR:
{
    arg.get_value<void*>() = as_void_ptr(std::addressof(get_value(src_data)));
}
// std::nullptr_t也不会有什么包装类了,直接返回std::nullptr_t的type实例即可
case variant_policy_operation::GET_RAW_TYPE:
{
    arg.get_value<type>() = type::get<std::nullptr_t>();
    break;
}
// 和void一样,arg通过传入data_address_container作为地址容器带走一波数据
case variant_policy_operation::GET_ADDRESS_CONTAINER:
{
    data_address_container& data = arg.get_value<data_address_container>();
    data.m_type = type::get<std::nullptr_t>();
    data.m_wrapped_type = type::get<std::nullptr_t>();
    data.m_data_address = as_void_ptr(raw_addressof(get_value(src_data)));
    data.m_data_address_wrapped_type = as_void_ptr(wrapped_raw_addressof(get_value(src_data)));
    break;
}
// 和void一样,判断tuple<0>的类型是不是std::nullptr_t,结果通过tuple<1>返回出去
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);
    ok = true;
    return rhs.is_nullptr();
}
// 只有在tuple<0>是nullptr并且tuple<1>不是nullptr时成立
case variant_policy_operation::COMPARE_LESS:
{
    const auto& param = arg.get_value<std::tuple<const variant&, const variant&, bool&>>();
    const variant& lhs = std::get<0>(param);
    const variant& rhs = std::get<1>(param);
    bool& ok = std::get<2>(param);
    ok = true;
    return (lhs.is_nullptr() && !rhs.is_nullptr());
}

发表评论