【问题标题】:Smart pointer toolkit using variadic CRTP使用可变参数 CRTP 的智能指针工具包
【发布时间】:2021-03-29 23:11:06
【问题描述】:

我即将设计和实现一种智能指针工具包——一组类来定义各种类型的智能指针,如 unique_ptr、intrusive_ptr、shared_ptr、observing_ptr、tagged_ptr 等。顺便提一下,我在独立环境中工作我没有可用的 c++ 库。我的干预是避免代码重复,使其遵循优雅的设计原则。让我在里面描述一下我的想法。

设计注意事项: 我想使用可变 CRTP 方法来混合所需的指针特性,即特征。对于每个特征集,都应该有一个特征类,例如:

/* Functions to support move semantics like move constructor, move assignment operator */
template<typename DERIVED>
class MoveablePointer { ... };

/* Functions to manage pointee lifetime - using the deleter class */
/* EDIT: template<typename DERIVED, typename DELETER = DefaultDeleter<typename DERIVED::element_type>> */
template<typename DERIVED, typename DELETER> /* <-------- Default removed here as EDIT */
class Owning { 
public:
    using deleter_type = DELETER;
    
    /* ... */
};

/* Functions to use least significant bits effectively unused due to alignment to hold additional payload information */
template<typename DERIVED, typename TAGS, size_t ALIGNMENT>
class Tagged { ... };

然后使用可变 CRTP 模式将特征混合到一个智能指针类中:

template<template<typename> class... TRAITS>
struct make_traits {
    template<typename DERIVED>
    struct Traits : public TRAITS<DERIVED>... {};
};
template<typename T, template<typename> class POINTER_TRAITS>
class SmartPointer : public POINTER_TRAITS<SmartPointer<T, POINTER_TRAITS>> {
public:
    using pointer = T*;
    using element_type = T;

    /* ... */
};

template<typename T, typename DELETER = DefaultDeleter<T>>
using unique_ptr = SmartPointer<T, make_traits<MoveablePointer, Owning>>;

template<typename T>
using observer_ptr = SmartPointer<T, make_traits<Observing, NonOwning, Copyable, Moveable>>;

/* ... and to continue defining type aliases to cover various smart pointer variations... */

基本上,一旦特定特征具有相同的模板参数集(仅template&lt;typename DERIVED&gt;),这个想法似乎就有效。但如上所示,情况并非如此,例如 Tagged 特征或 Owning 特征分别需要更多模板参数,例如 ALIGNMENTDELETER

所以我的问题是 - 如何更改 make_traits 和 SmartPointer 类模板的实现以支持可变参数 trait 的模板参数?

非常感谢愿意帮助我的人!马丁

编辑:随着讨论在答案下方流动而调整代码...

【问题讨论】:

    标签: c++ variadic-templates smart-pointers c++20 crtp


    【解决方案1】:

    你可以使用可变参数模板:

    template<template<typename, typename...> class... TRAITS>
    //                        ^^^^^^^^^^^^^
    struct make_traits {
        template<typename DERIVED>
        struct Traits : public TRAITS<DERIVED>... {};
    };
    template<typename T, template<typename> class POINTER_TRAITS>
    class SmartPointer : public POINTER_TRAITS<SmartPointer<T, POINTER_TRAITS>> {
    public:
        using pointer = T*;
        using element_type = T;
    
        /* ... */
    };
    
    template<typename T, typename DELETER = DefaultDeleter<T>>
    using unique_ptr = SmartPointer<T, make_traits<MoveablePointer, Owning>::template Traits>;
    
    template<typename T>
    using observer_ptr = SmartPointer<T, make_traits<Observing, NonOwning, Copyable, MoveablePointer>::template Traits>;
    

    Demo

    【讨论】:

    • 一旦我尝试从上面的代码中实例化unique_ptr,它会因为期望make_traits::Traits 中有两个模板参数而失败。我认为原因是在unique_ptr 类型别名中缺少DELETEROwning 的“转发”......如果是这样,怎么办?
    • @MartinKopecký:CRTP 的问题是,Derived 在 CRTP 中是不完整的类型。你必须创建外部特征而不是使用 Derived::type: Demo
    • 太好了,这解决了Owning 类定义中DELETER 的默认类型的问题。这是定义DELETER(使用默认值)的唯一方法还是可以在unique_ptr 类型别名中以某种方式定义类型? - 拥有DELETER,假设在任何地方都没有默认值/仅在using unique_ptr = ... 中默认值我已经编辑了我的原始代码以反映这一点
    • 我建议针对这个特定问题提出另一个问题。 (我认为哨兵类型可能会完成这项工作。)
    • 感谢 Jarod42 的帮助。我在这里创建了后续问题:stackoverflow.com/q/65375096/5677080
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 2021-07-22
    • 2015-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多