std::使用写入时复制分支转发

std::forward with copy-on-write branching

本文关键字:复制 分支 转发 std      更新时间:2023-10-16

我正在尝试做一些事情来达到

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

这样

  1. 如果foo()t进行更改,它将在副本上运行。(类似于写入时复制(

  2. 一旦foo()完成tt就会直接转发给bar()

这可能吗?写的是否正确?编译器会理解我想要做什么吗?

我是否需要创建一些帮助程序类来实现这一点?

同样,如果我尝试以下情况怎么办:

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

这样

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

写入时复制是类的属性,没有好方法可以在somemethod中发生这种情况。 你可以防止foo意外修改参数,方法是给它一个const参数,你正在这样做,但你也把它作为一个右值传递,这是不必要的,而且很奇怪。我从未见过const T&&的用例. 人们要么使用const T&,要么使用T&T&&。 在您的情况下,我会推荐const T&.

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 引用,但这对于任何理智的情况来说都是矫枉过正的。

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

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的任何地方都使用它,这可能是一个更好的解决方案。