Boost logo

Boost :

Subject: Re: [boost] [ValueRef]
From: THOMAS JORDAN (tomjordan766_at_[hidden])
Date: 2015-04-21 04:41:03


> Message: 7
> Date: Mon, 20 Apr 2015 18:39:57 +0000 (UTC)
> From: Joaquin M Lopez Munoz <joaquin_at_[hidden]>
> To: boost_at_[hidden]
> Subject: Re: [boost] [ValueRef]
> Message-ID: <loom.20150420T202848-660_at_[hidden]>
> Content-Type: text/plain; charset=utf-8

> THOMAS JORDAN <tomjordan766 <at> gmail.com> writes:

>>
> > > From: Andrey Semashev <andrey.semashev <at> gmail.com>
> >
> > > Is this similar to Boost.Flyweight?
> >
> > It is similar in that both provide a 'smart' handle which can be used
> > pretty much as a drop in for the wrapped type.
> >
> > However, Boost.Flyweight requires the wrapped type to be hashable.

> Not necessarily; set_factory, for instance, requires values to
> be less-than comparable:

>
http://boost.org/libs/flyweight/doc/tutorial/configuration.html#set_factory

Ok

> Also, see below.

> > Also, there is a level of indirection with Flyweight which can mean that
> > unnecessary temps may need to be created to do the initial lookup (and
> > addition) to the Flyweight store, unless you use the Flyweight key-map
> > interface.

> Boost.Flyweight uses move semantics and perfect fwd ction where available,
> I don't see how another solution can do better on this front

Agreed, I'll withdraw that statement. However, as I said in the O.P., the
ValueRef implementation I have done is currently only C++03. It uses a
combination of N x forwarding constructor overloads taking arguments by
const reference, and the client can use reference wrappers to forward to
lvaluesto do the non-perfect forwarding (as boost.shared_ptr make_shared
does) . The intention in the final library would be to support
C++11/perfect forwarding and possibly Boost.Move for C++03 move semantics.
So they would be equivalent in that regard.

> > ValueRef does not use 'flyweighting.' That is, if there are two
> > ValueRefs created independently with the same value, e.g.,
> >
> > ValueRef<std::vector<int> > v1(10,10), v2(10,10);
> >
> > there will be two separate wrapped vector<int> objects - it is only when
> > copying/assigning that sharing takes place. It is simpler than Flyweight
> > and is essentially intended to be a more value-orientated option to
> > shared-ptr-to-const.

> The lib is extensible to the point that ValueRef can potentially be
> built on top of it:

> template<typename Entry,typename Key>
> struct ValueRefFactory
> {
> using handle_type=Entry*;

> template <typename E>
> handle_type insert(E&& x){return new Entry{std::forward<E>(x)};}
> void erase(handle_type h){delete h;}
> const Entry& entry(handle_type h){return *h;}
> };

> template<typename T>
> using ValueRefImpl=flyweight<
> T,no_locking,
> factory<ValueRefFactory<boost::mpl::_1,boost::mpl::_2>>>;

> template<typename T>
> struct ValueRef:ValueRefImpl<T>
> {
> using impl_type=ValueRefImpl<T>;
> const impl_type& impl()const{return *this;}
> using impl_type::impl_type;
> ValueRef(const ValueRef&x):impl_type(x.impl()){}
> ValueRef(ValueRef&x):impl_type(x.impl()){}
> ValueRef(const ValueRef&&x):impl_type(x.impl()){}
> ValueRef(ValueRef&&x):impl_type(x.impl()){}
> using impl_type::operator=;
> const T& operator*()const{return this->get();}
> const T* operator->()const{return &this->get();}
> bool identity(const ValueRef& x)const{return &**this==&*x;}
> };

> See complete example at:

> http://coliru.stacked-crooked.com/a/c33389766fac6ecb

> (except the unique_instance bit, which can be done, but admittedly
> with more effort).

> > Another (less significant) difference is that ValueRef
> > currently has no dependency on MPL, which I believe Flyweight does,
though
> > that could well change if needed.

> Boost.Flyweight is indeed heavier on the include side than some
> people might be comfortable with.

I think this is my concern with having Boost Flyweight as the only option
for what is a relatively simple type. ValueRef is currently about 350 lines
of easy-to-understand code in a single header file, and has no dependencies
on MPL or any other Boost or std libraries, with the exception of an atomic
library.
It is intended in particular as a lightweight, clean replacement for
shared-ptr-to-const, which I see used a lot in code. I also unfortunately y
see shared-ptr-to-non-const being used a lot when people should be
using shared-ptr-to-const, which is less safe and makes it much harder to
reason about what is going on.
ValueRef is an explict, consistent and safe alternative to such
(mis)usages, and would also sit more comfortably with people who have
concerns about build times, library-dependencies and cross-platform issues,
etc.

> Joaqu?n M L?pez Mu?oz
> Telef?nica

Tom.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk