Non owning owner with destination semantics

I have a class that should contain a link to some data without owning this data (that is, the actual data is guaranteed not to go beyond). In particular, the class cannot make a copy - the data is easily several gigabytes in size.

Now the usual implementation (I assume) should have a link to the data:

struct holder_ref {
    type const& value;

    holder_ref(type const& value) : value(value) { }
};

(Note that constthis has nothing to do with the problem).

Now I need this class to be assigned (i.e. work operator =). I thought this was a fairly common problem, but I can't remember how (ever) I solved it before.

The problem is that the link cannot be assigned, and theres simply not. The only solution Ive come up with, instead of a new assignment operator, is using a new layout:

// x = other_x; gets replaced with:
x.~T();
new (&x) T(other_x);

Now it works and conforms to the standard. But it is probably ugly. No - unacceptable.

So I'm looking for alternatives. One idea is to use pointers, but Im not sure if my constructor is actually guaranteed to work (and passing a pointer is not possible because of the interface I have to stick to):

struct holder_ptr {
    type const* value;

    // Is this legal?
    holder_ptr(type const& value = 0) : value(&value) { }
};

But I'd rather use a link, if at all possible. Only - how to implement the assignment operator?

struct holder_ref {
    type const& value;

    holder_ref(type const& value = 0) : value(value) { }

    holder_ref& operator =(holder_ref const& other) {
        // Now what?!
        return *this;
    }
};

As a test example, consider the following code:

int main() {
    int const TEST1 = 23;
    int const TEST2 = 13;
    int const TEST3 = 42;
    std::vector<holder_ptr> hptr(1);
    std::vector<holder_ref> href(2);

    // Variant 1. Pointer.
    hptr[0] = holder_ptr(TEST1);

    // Variant 2. Placement new.
    href[0].~holder_ref();
    new (&href[0]) holder_ref(TEST2);

    // Variant 3. ???
    href[1] = holder_ref(TEST3);

    assert(*hptr[0].value == TEST1);   // Works (?)
    assert(href[0].value == TEST2);    // Works
    assert(href[1].value == TEST3);    // BOOM!
}

(Also, just to make it clear - the type was talking about non-POD, and I need a standard compatible solution.)

+3
3

holder_ptr. :

struct bad_holder : std::exception { };

struct holder_ptr {
    holder_ptr() : value(0) { }
    holder_ptr(type const& value) : value(&value) { }

    type const& get() { 
        if (value == 0) throw bad_holder();
        return *value; 
    }
private:
    type const* value;
};

, , , ( " " , , ' undefined).

, , . , , ( , , ).

. , .

+6

. , , operator=:

holder_ref& operator =(holder_ref const& other) {
    new (this) holder_ref(other);
    return *this;
}
+3

Is the TR1 weak_ptr standard adequate enough?

+1
source

All Articles