草庐IT

c++ - 带有自定义删除器的 std::shared_ptr 的 Typedef 别名

coder 2024-02-22 原文

我想为 std::shared_ptr 创建别名使用自定义删除器。

此代码有效,但仅适用于唯一指针。我收到有关标有 [ 1 ] 的行的无效模板参数数量的错误。

我注意到 std::unique_ptr 的模板和 ctor 参数和 std::shared_ptr与所列不同 herehere

我注意到这个问题可能与 this 重复, 但我不知道如何解决我的问题

#include <memory>
#include <iostream>

template<class T>
struct Deleter {
    void operator()(T* p) const noexcept {
       p->Drop(); // SFINAE
    };
};

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

//template <class T>
//using my_shared_ptr = std::shared_ptr<T, Deleter<T>>; // [1] does not work
//using my_shared_ptr = std::shared_ptr<my_unique_ptr<T>>; // this is pointless

template <class T>
using my_shared_ptr = std::shared_ptr<T>;


template <class T, class... Args>
my_unique_ptr<T> my_make_unique(Args&&... args)
{
    return my_unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template <class T, class... Args>
std::shared_ptr<T> my_make_shared(Args&&... args)
{
    return {new T(std::forward<Args>(args)...), Deleter<T>{}};
//  return {new T(std::forward<Args>(args)...), Deleter<T>()}; this also works
}

class MyClass{
    public:
      MyClass() 
      {
          std::cout << "Default ctor\n";
      }
      ~MyClass()
      {
          std::cout << "Default dtor\n";
      }
      void Drop()
      {
          std::cout << "Custom deleter\n";
          delete this;
      }
};

int main()
{
    {
        my_unique_ptr<MyClass> p1(new MyClass);
        my_unique_ptr<MyClass> p2 = my_make_unique<MyClass>();
    }

    {
//      my_shared_ptr<MyClass> p(new MyClass) // [2] does not work
//      my_shared_ptr<MyClass> p(my_make_unique<MyClass>()); // [3] does not work
        std::shared_ptr<MyClass> p1 = my_make_shared<MyClass>(); // [4] works
        my_shared_ptr<MyClass> p2 = my_make_shared<MyClass>();
    }
}

对于[ 2 ]
我如何让它知道使用我的删除器?

对于 [ 3 ] 如果 [ 2 ] 不可能,那么我该如何创建一个可以创建 my_shared_ptr<T> 的函数?给我?

[ 1 ] 错误

main.cpp:15:51: error: wrong number of template arguments (2, should be 1)
 using my_shared_ptr = std::shared_ptr<T, Deleter<T>> // does not work
                                                   ^~
In file included from /usr/local/include/c++/6.3.0/bits/shared_ptr.h:52:0,
                 from /usr/local/include/c++/6.3.0/memory:82,
                 from main.cpp:1:
/usr/local/include/c++/6.3.0/bits/shared_ptr_base.h:343:11: note: provided for 'template<class _Tp> class std::shared_ptr'
     class shared_ptr;
           ^~~~~~~~~~

[ 2 ] 错误

In file included from /usr/local/include/c++/6.3.0/bits/shared_ptr.h:52:0,
                 from /usr/local/include/c++/6.3.0/memory:82,
                 from main.cpp:1:
/usr/local/include/c++/6.3.0/bits/shared_ptr_base.h: In instantiation of 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(_Tp1*) [with _Tp1 = MyClass; _Tp = std::unique_ptr<MyClass, Deleter<MyClass> > __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]':
/usr/local/include/c++/6.3.0/bits/shared_ptr.h:117:32:   required from 'std::shared_ptr<_Tp>::shared_ptr(_Tp1*) [with _Tp1 = MyClass; _Tp = std::unique_ptr<MyClass, Deleter<MyClass> >]'
main.cpp:48:45:   required from here
/usr/local/include/c++/6.3.0/bits/shared_ptr_base.h:885:39: error: cannot convert 'MyClass*' to 'std::unique_ptr<MyClass, Deleter<MyClass> >*' in initialization
         : _M_ptr(__p), _M_refcount(__p)
                                       ^

编辑 已添加 my_make_shared函数,现在 [4] 可以正常编译。

编辑 我注意到(通过观察错误)我的别名 shared_ptr<MyClass>不是 shared_ptr<MyClass> 的真正别名,而是 shared_ptr<unique_ptr<MyClass>> 的别名- 它正在尝试创建一个指向指针的指针(起初我认为它只是重定向构造函数)

编辑 注释掉指向指针的别名。使用 [ 1 ] 和 [ 3 ] 的想法确实没有意义甚至可能没有意义

为 shared_ptr 添加了新的(正确的)别名

编辑

整个代码现在可以工作了。所有问题都解决了。

编辑 最后一个小问题:
为什么我不能改变 return my_unique_ptr<T>(new T(std::forward<Args>(args)...));return {new T(std::forward<Args>(args)...)};

我收到这个错误:

main.cpp: In instantiation of 'my_unique_ptr<T> my_make_unique(Args&& ...) [with T = MyClass; Args = {}; my_unique_ptr<T> = std::unique_ptr<MyClass, Deleter<MyClass> >]':
main.cpp:56:61:   required from here
main.cpp:26:63: error: converting to 'my_unique_ptr<MyClass> {aka std::unique_ptr<MyClass, Deleter<MyClass> >}' from initializer list would use explicit constructor 'std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = MyClass; _Dp = Deleter<MyClass> std::unique_ptr<_Tp, _Dp>::pointer = MyClass*]'
                     return {new T(std::forward<Args>(args)...)};
                                                               ^

了解 std::unique_ptr 的那个 ctor是明确的,但是 std::shared_ptr 的构造函数不是。

非常感谢您的帮助!

最佳答案

你可以做一个my_make_shared ,类似于:

template <class T, class... Args>
std::shared_ptr<T> my_make_shared(Args&&... args)
{
    return {new T(std::forward<Args>(args)...), Deleter<T>{}};
}

用法:

 std::shared_ptr<MyClass> p(my_make_shared<MyClass>());

对于 [3],它应该是:

 std::shared_ptr<MyClass> p(my_make_unique<MyClass>());

请注意 std::shared_ptr<std::unique_ptr<T/*, D*/>>大多是毫无意义的。

关于c++ - 带有自定义删除器的 std::shared_ptr 的 Typedef 别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41882267/

有关c++ - 带有自定义删除器的 std::shared_ptr 的 Typedef 别名的更多相关文章

  1. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

  2. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  3. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  4. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  5. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  6. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  7. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  10. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

随机推荐