【问题标题】:How can I make a valid C++ alias template for std::unique_ptr如何为 std::unique_ptr 制作有效的 C++ 别名模板
【发布时间】:2017-07-22 19:20:07
【问题描述】:

我想为std::unique_ptr 制作一个别名模板,它提供我自己的删除器功能。

unique_ptr 有一个标量和一个数组实现,它们的定义如下:

template <class T, class D = default_delete<T>>
class unique_ptr // scalar

template <class T, class D>
class unique_ptr<T[], D> // array

我在尝试覆盖unique_ptr 的标量和数组版本时遇到了麻烦。为一个版本创建别名很容易,如下所示:

template<class T>
struct Deleter {
    void operator()(T* ptr) { delete ptr; }
};

template<class T>
using my_unique_ptr = std::unique_ptr<T Deleter<T>>;

但是当我尝试添加第二个别名时,像这样:

template<class T>
struct ArrayDeleter {
    void operator()(T* ptr) { delete [] ptr; }
};
template<class T>
using my_unique_ptr = std::unique_ptr<T[], ArrayDeleter<T>>;

...我最终会出现编译器错误,因为“my_unique_ptr”不明确。

我的问题是:如何创建一个别名同时适用于 unique_ptr 的数组和标量版本?

【问题讨论】:

    标签: c++ arrays c++11 templates unique-ptr


    【解决方案1】:

    您似乎正在尝试专门化 using 声明。你可能不会。

    template<class T>
    struct my_unique_ptr_helper {
      using type = std::unique_ptr<T, Deleter<T>>;
    };
    template<class T>
    struct my_unique_ptr_helper<T[]> {
      using type = std::unique_ptr<T[], ArrayDeleter<T>>;
    };
    
    template<class T>
    using my_unique_ptr = typename my_unique_ptr_helper<T>::type;
    

    现在这有缺点,因为它相当完全地阻止了扣除。

    我们可以通过将专精转移到别处来解决这个问题。

    template<class T>
    struct Deleter {
      void operator()(T* ptr) const {
        delete ptr;
      }
    };
    template<class T>
    struct ArrayDeleter {
      void operator()(T* ptr) const {
        delete[] ptr;
      }
    };
    template<class T>
    struct Deleter<T[]>:ArrayDeleter<T> {}; // inheritance
    

    现在:

    template<class T>
    using my_unique_ptr = std::unique_ptr<T, Deleter<T>>;
    

    更简单,并且可以允许更多地扣除T

    当然,这一切都毫无意义,但我认为你真正的Deleterstd::default_delete 不一样。

    【讨论】:

    • 这对我有用,谢谢。我根本不需要制作 ArrayDeleter 结构。相反,我创建了一个通用的“template Deleter”以及一个针对 T[] 的 Deleter 特化。
    【解决方案2】:

    您应该向我们展示您的ArrayDeleter,但是...您确定不能用独特的usingstd::conditional 解决您的问题吗?

    我的意思是,像

    template <typename T>
    using my_unique_ptr = std::unique_ptr<T,
             typename std::conditional<std::is_array<T>::value,
                                       ArrayDeleter<T>,
                                       Deleter<T>>::type>;
    

    --- 编辑---

    OP 说

    我已编辑问题以包含示例 ArrayDeleter 实现

    不确定(我在模板数组专业化方面犯了很多错误),但我想如果你可以修改 ArrayDeleter 如下所示,那应该可以工作

    template <typename>
    struct ArrayDeleter;
    
    template <typename T>
    struct ArrayDeleter<T[]>
     { void operator()(T* ptr) { delete [] ptr; } };
    

    【讨论】:

    • 我已编辑问题以包含示例 ArrayDeleter 实现。
    • @DominicDosSantos - 答案改进;希望这会有所帮助
    猜你喜欢
    • 2014-08-26
    • 2016-06-28
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    相关资源
    最近更新 更多