草庐IT

c++ - shared_ptr<T> 到 shared_ptr<T const> 和 vector<T> 到 vector<T const>

coder 2023-11-13 原文

我正在尝试为我的软件定义一个好的设计,这意味着要小心对某些变量的读/写访问。这里我简化了讨论的程序。希望这对其他人也有帮助。 :-)

假设我们有一个类 X,如下所示:

class X {
    int x;
public:
    X(int y) : x(y) { }
    void print() const { std::cout << "X::" << x << std::endl; }
    void foo() { ++x; }
};

我们还可以说,将来这个类将被子类化为 X1、X2...,它可以重新实现 print()foo() . (为了简单起见,我在这里省略了必需的 virtual 关键字,因为这不是我面临的实际问题。)

因为我们将使用多态性,所以让我们使用(智能)指针并定义一个简单的工厂:

using XPtr = std::shared_ptr<X>;
using ConstXPtr = std::shared_ptr<X const>;

XPtr createX(int x) { return std::make_shared<X>(x); }

到现在为止,一切都很好:我可以定义 goo(p)可以读写phoo(p)只能读取 p .

void goo(XPtr p) {
    p->print();
    p->foo();
    p->print();
}

void hoo(ConstXPtr p) {
    p->print();
//    p->foo(); // ERROR :-)
}

调用站点如下所示:

    XPtr p = createX(42);

    goo(p);
    hoo(p);

指向 X 的共享指针 ( XPtr ) 自动转换为其常量版本 ( ConstXPtr )。很好,这正是我想要的!

麻烦来了:我需要一个 X 的异构集合.我的选择是 std::vector<XPtr> . (它也可以是 list ,为什么不呢。)

我想到的设计如下。我有两个版本的容器:一个对其元素具有读/写访问权限,另一个对其元素具有只读访问权限。

using XsPtr = std::vector<XPtr>;
using ConstXsPtr = std::vector<ConstXPtr>;

我有一个类可以处理这些数据:

class E {
    XsPtr xs;
public:
    E() {
        for (auto i : { 2, 3, 5, 7, 11, 13 }) {
            xs.emplace_back(createX(std::move(i)));
        }
    }

    void loo() {
        std::cout << "\n\nloo()" << std::endl;
        ioo(toConst(xs));

        joo(xs);

        ioo(toConst(xs));
    }

    void moo() const {
        std::cout << "\n\nmoo()" << std::endl;
        ioo(toConst(xs));

        joo(xs); // Should not be allowed

        ioo(toConst(xs));
    }
};

ioo()joo()功能如下:

void ioo(ConstXsPtr xs) {
    for (auto p : xs) {
        p->print();
//        p->foo(); // ERROR :-)
    }
}

void joo(XsPtr xs) {
    for (auto p: xs) {
        p->foo();
    }
}

如您所见,在 E::loo() 中和 E::moo()我必须用 toConst() 做一些转换:

ConstXsPtr toConst(XsPtr xs) {
    ConstXsPtr cxs(xs.size());
    std::copy(std::begin(xs), std::end(xs), std::begin(cxs));
    return cxs;
}

但这意味着一遍又一遍地复制所有内容.... :-/

另外,在 moo() ,这是常量,我可以调用joo()这将修改 xs的数据。不是我想要的。在这里我更喜欢编译错误。

完整代码可在 ideone.com 获得.

问题是:是否可以在不将 vector 复制到其 const 版本的情况下执行相同的操作?或者,更一般地说,是否有既高效又易于理解的好技术/模式?

谢谢。 :-)

最佳答案

我认为通常的答案是对于类模板 X<T> , 任何 X<const T>可以专门化,因此不允许编译器简单地假设它可以转换 X<T> 的指针或引用至 X<const T>并且没有通用的方式来表达这两个实际上是可转换的。但后来我想:等等,有一种方法可以说 X<T> 是一个 X<const T> . IS A 通过继承来表达。

虽然这对 std::shared_ptr 没有帮助或标准容器,这是您在实现自己的类时可能希望使用的一种技术。事实上,我想知道是否std::shared_ptr并且可以/应该改进容器以支持这一点。谁能看出这有什么问题吗?

我想到的技术会像这样工作:

template< typename T > struct my_ptr : my_ptr< const T >
{
    using my_ptr< const T >::my_ptr;
    T& operator*() const { return *this->p_; }
};

template< typename T > struct my_ptr< const T >
{
protected:
    T* p_;

public:
    explicit my_ptr( T* p )
      : p_(p)
    {
    }

    // just to test nothing is copied
    my_ptr( const my_ptr& p ) = delete;

    ~my_ptr()
    {
        delete p_;
    }

    const T& operator*() const { return *p_; }
};

Live example

关于c++ - shared_ptr<T> 到 shared_ptr<T const> 和 vector<T> 到 vector<T const>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19616586/

有关c++ - shared_ptr<T> 到 shared_ptr<T const> 和 vector<T> 到 vector<T const>的更多相关文章

  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-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代码修改为

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

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

  4. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  5. ruby-on-rails - Nokogiri:使用 XPath 搜索 <div> - 2

    我使用Nokogiri(Rubygem)css搜索寻找某些在我的html里面。看起来Nokogiri的css搜索不喜欢正则表达式。我想切换到Nokogiri的xpath搜索,因为这似乎支持搜索字符串中的正则表达式。如何在xpath搜索中实现下面提到的(伪)css搜索?require'rubygems'require'nokogiri'value=Nokogiri::HTML.parse(ABBlaCD3"HTML_END#my_blockisgivenmy_bl="1"#my_eqcorrespondstothisregexmy_eq="\/[0-9]+\/"#FIXMEThefoll

  6. ruby-on-rails - 如何重构 "shared"方法? - 2

    我正在使用RubyonRails3.2.2,我想从我的模型/类中“提取”一些方法。也就是说,在不止一个类/模型中,我有一些方法(注意:方法与用户授权相关,并被命名为“CRUD方式”),这些方法实际上是相同的;所以我认为DRY方法是将这些方法放在“共享”模块或类似的东西中。实现该目标的常见且正确的方法是什么?例如,我应该将“共享”代码放在哪里(在哪些目录和文件中)?如何在我的类/模型中包含提到的方法?你有什么建议?注意:我正在寻找“RubyonRails制作东西的方式”。 最佳答案 一种流行的方法是使用ActiveSupport关注点

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  9. ruby-on-rails - 没有参数的 `<<`(小于两倍)是什么意思? - 2

    我在一个我想在formtasticGem中覆盖的方法中找到了这个。该方法如下所示:defto_htmlinput_wrappingdohidden_field_html是什么意思?在第三行做什么?我知道它对数组有什么作用,但在这里我不知道。 最佳答案 你可以这样读:hidden_field_htmllabel_with_nested_checkbox是连接到hidden_​​field_html末尾的参数-为了“清晰”,他们将其分成两行 关于ruby-on-rails-没有参数的`

  10. ruby-on-rails - 找不到 gem railties (>= 0.a) (Gem::GemNotFoundException) - 2

    我已经看到了一些其他的问题,尝试了他们的建议,但没有一个对我有用。我已经使用Rails大约一年了,刚刚开始一个新的Rails项目,突然遇到了问题。我卸载并尝试重新安装所有Ruby和Rails。Ruby很好,但Rails不行。当我输入railss时,我得到了can'tfindgemrailties。我当前的Ruby版本是ruby2.2.2p95(2015-04-13修订版50295)[x86_64-darwin15],尽管我一直在尝试通过rbenv设置ruby​​2.3.0。如果我尝试rails-v查看我正在运行的版本,我会得到同样的错误。我使用的是MacOSXElCapitan版本10

随机推荐