mr-edd.co.uk :: horsing around with the C++ programming language

value_ptr

value_ptr is a so-called smart pointer. Really, it wants to be a smart reference, but you can't overload the . operator in C++, so -> had to do. Because the use of the -> operator makes it feel like you're using a pointer, it is named as such. I'm not really happy with the name. If you can think of a better one, answers on a post card please…

In short, when a value_ptr is copied, it performs a deep copy of the pointee. There are lots of existing smart pointers designed for this purpose, but I found them lacking in some respect. Most notably value_ptr has the following features:

Recent activity

Code

Clone the repository using mercurial:

> hg clone http://bitbucket.org/edd/value_ptr

Or get a zip file of the code.

Quick start

By default value_ptr will use the copy constructor of the type used for initialization:

#include <iostream>
#include <string>
#include <value_ptr.hpp>

class base
{
    public:
        base() : number(0) { }
        virtual ~base() { }
        virtual std::string name() const { return "base"; }

        unsigned number;
};

class derived : public base
{
    public:
        virtual std::string name() const { return "derived"; }
};

int main()
{
    derived d;
    value_ptr<base> p(d); // note we don't pass a pointer, here.

    // even though the type of p is value_ptr<base>, it really points to a derived
    std::cout << p->name() << '\n'; // "derived"

    value_ptr<base> p2(p);

    p2->number = 42;

    // copying a value_ptr copies the pointee via the copy constructor by default
    std::cout << p2->number << '\n'; // 42
    std::cout << p->number << '\n'; // 0
    std::cout << p2->name() << '\n'; // "derived"
}

value_ptr can also use cloning functionality from your existing hierarchies and will prevent slicing by throwing an exception or triggering an assertion (your choice).

Further reading

Comments

brian (rip-off)

[17/12/2007 at 16:45:00]

Impressive. I'll certainly consider using it next time I am programming and need something with its particular semantics.

antred

[06/09/2010 at 14:59:41]

Have you considered trying to get this officially accepted into the boost library?

Edd

[10/09/2010 at 17:53:41]

The thought has crossed my mind, but this kind of thing appears with some regularity on the mailing list and there's disagreement on the best approach.

I'm happy to leave it alone, but feel free to champion it on the mailing list if you think it's worth it :)

alfC

[01/03/2011 at 21:29:39]

Yes, it is unfortunate and sane at the same time that we can't overload the . "operator". (But your blog is not about sanity (which I like) so it is just unfortunate.) Otherwise we could have perfect type erasure for hierarchies. However, have you though in overloading some other operator. like "|" or "*" or "&&" so it looks "less" like a pointer:

  value_ptr<base> p(d);
  //std::cout << p->name() << '\n';
  std::cout << p|&base::name();  //not sure about the precedence of operators

maybe some combination of operators are better for precedence. (or Maybe this can't be used for virtual functions). -- Thanks,

Edd

[03/03/2011 at 23:19:24]

Re sanity: derived classes do it. I don't see why you couldn't have some other kind of proxy mechanism with the same name resolution rules (off the top of my head). But perhaps adding even more complexity to C++ isn't such a great idea :)

I think p|&base::name() would have to be (p|&base::name)() which is already looking a bit noisy to me. Even though I'd prefer to use a '.' over a '->', it's not too bad on the whole. Nice thought, though.

(optional)
(optional)
(required, hint)

Links can be added like [this one -> http://www.mr-edd.co.uk], to my homepage.
Phrases and blocks of code can be enclosed in {{{triple braces}}}.
Any HTML markup will be escaped.