【问题标题】:std::forward with copy-on-write branching带有写时复制分支的 std::forward
【发布时间】:2014-10-13 17:47:13
【问题描述】:

我正在尝试做一些事情

template <typename T>
void somemethod (T&& t) {
    foo(static_cast<const T&>(t));
    bar(std::forward<T>(t));
}

这样

  1. 如果foo()t 进行了更改,它将改为对副本进行操作。 (类似于写时复制)

  2. 一旦foo() 使用t 完成,t 将直接转发到bar()

这可能吗?写的对吗?编译器会理解我想要做什么吗?

我需要创建一些帮助类来实现它吗?

同样,如果我尝试的结果是:

template <typename T>
void somemethod (T&& t) {
    foo(std::forward<T>(t));
    bar(std::forward<T>(t));
}

这样

  1. foo() 使用的相同t 然后被转发到bar()

【问题讨论】:

  • “我很确定这意味着写时复制” 好吧,不是真正的免费功能,你会失去 copy在这种情况下,除非您提供一些允许访问此副本的返回值。

标签: c++ perfect-forwarding


【解决方案1】:

Copy-on-write 是一个类的属性,没有好的方法可以在somemethod 中导致这种情况发生。您可以防止foo 意外修改参数,方法是给它一个const 参数,您正在这样做,但您也将它作为右值传递,这是不必要的,并且奇怪。我从未见过const T&amp;&amp; 的用例。人们要么使用const T&amp;,要么使用T&amp;,要么使用T&amp;&amp;。在你的情况下,我会推荐const T&amp;

template<class T> //I'm assuming you forgot to paste this bit
void somemethod (T&& t) {
    foo(static_cast<const T&>(t));
    bar(std::forward<T>(t));
}

如果你真的想绝对确定foo 在任何情况下都不能破坏t,你可以给它一个t 的副本而不是const 引用,但那是在任何理智的情况下都矫枉过正。

【讨论】:

    【解决方案2】:

    这个问题可能有更好的解决方案,但你可以这样做

    template <typename T>
    void somemethod (T&& t) {
        T tmp_t = foo(std::forward<T>(t));
        bar(std::forward<T>(tmp_t));
    }
    

    甚至更简单:

    template <typename T>
    void somemethod (T&& t) {
        bar(foo(std::forward<T>(t)));
    }
    

    这样 foo 可以报告它是否真的改变了任何东西,但它的签名必须改变:

    template <typename T>
    T foo(T&& t){
        if (want_to_modify){
            T result;
            // here you insert data that get modified form t
            return std::forward<T>(result);
        }else{
            return std::forward<T>(t);
        }
    }
    

    }

    这样,T 的实例如果没有被修改,就会直接通过 foo

    其他方法是直接在T 中实现写时复制,但如果您在使用T 的任何地方都不需要它,这可能是一个更好的解决方案。

    【讨论】:

      猜你喜欢
      • 2012-01-21
      • 2015-08-21
      • 2022-01-05
      • 2016-03-21
      • 2015-07-20
      • 2016-08-22
      • 2014-06-12
      • 2016-07-08
      • 2020-10-04
      相关资源
      最近更新 更多