简体   繁体   中英

How do I extend rvalue lifetime to my custom container lifetime?

Let me have a custom wrapper container. I want to use it like this:

double d = 3.14;
MyContainer<std::vector<int>> pointer = new std::vector<int>();
MyContainer<std::string> rvalue = std::string("foo");
MyContainer<int> rvalue2 = 5 + 8;
MyContainer<double> lvalue = d;

I don't want to store copies of rvalues (a reference is OK). Rvalue references allow me to do like this:

std::string string1 = "foo";
std::string string2 = "bar";
std::string&& string3 = string1 + string2;
string3 += "test";

Basically I want to extend rvalues' lifetime to my container's lifetime. However when I do this:

template<class T>
class MyContainer {
public:
    MyContainer(T&& obj) : object(obj) {}
    T&& object
    ...
};
...
MyContaier<std::string> container = MyContainer(std::string("foo"));

I get an error (cannot bind 'std::string' lvalue to 'std::string&&'). The example is slightly different, but I just want to understand a general idea. How can I avoid this?

Besides that your code has multiple typos and syntax errors, there was nothing technically preventing you from taking an rvalue reference of std::string (although your assignment/constructor call is incorrect). Keeping a T&& as a member variable doesn't work like you think it does. Storing a reference to an expired rvalue and then accessing it would be UB as soon as you reach the next sequence point.

Here's a working example with a constructor for rvalue references and lvalue references. You need an actual instance inside your object if you want to "own" it. You can't technically extend the lifetime of an expiring rvalue; you can only construct something else that reuses it (and hopefully steals some of its expensive guts). Hope this helps.

#include <utility>
#include <string>
#include <iostream>

template<class T>
class MyContainer {
public:

    // makes a copy from an lvalue reference
    MyContainer(const T& obj)
        : object(obj) {
    }

    // moves from an rvalue reference
    MyContainer(T&& obj)
        : object(std::move(obj)) {
    }

    MyContainer& operator=(const T& obj) {
        object = obj;
    }

    MyContainer& operator=(T&& obj) {
        object = std::move(obj);
    }

    T object;
};

int main() {

    MyContainer<std::string> container = std::string("foo");
    std::cout << container.object;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM