Smart pointer toolkit using variadic CRTP

只愿长相守 提交于 2021-02-11 12:52:28

问题


I am about to design and implement a kind of smart pointer toolkit - a set of classes to define various types of smart pointers like unique_ptr, intrusive_ptr, shared_ptr, observing_ptr, tagged_ptr etc. Just to mention I am working in freestanding environment where I have no c++ library available. My intersion is to avoid code duplications, make it follow an elegant design principle. Let me describe my thoughts in there.

Design Considerations: I wanna use variadic CRTP approach to mixin the desired pointer features, the traits. For every feature set there shall be once trait class like:

/* 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 { ... };

and then to mixin the traits into one smart pointer class using variadic CRTP pattern:

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... */

Basically this idea seem to work once the particular traits have the same set of template arguments (just template<typename DERIVED>). But as sampled above, it is not the case as for instance the Tagged trait or Owning trait require more template parameters like ALIGNMENT or DELETER respectively.

So my question is - how to change the implementation of make_traits<> and SmartPointer<> class templates to support variadic trait's template arguments?

Many thanks to anyone willing to help me! Martin

EDIT: Code adjusted as the discussion flows below the answer...


回答1:


You might use variadic template:

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



来源:https://stackoverflow.com/questions/65371580/smart-pointer-toolkit-using-variadic-crtp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!