This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [c++0x] unique_ptr.hpp implementation


On 8/13/07, Howard Hinnant <hhinnant@apple.com> wrote:
>
> On Aug 12, 2007, at 5:52 PM, Jonathan Wakely wrote:
>
> > Both these problems can be avoided by getting rid of the
> > specialisation using enable_if.  See how the EBO is used in the
> > libstdc++ container types for a safe alternative e.g. _Vector_impl in
> > bits/stl_vector.h.
>
> Or for the more ambitious, put the compressed_pair optimization into
> tuple (which is really pretty easy given variadic templates), and
> then have unique_ptr<T, D> hold a tuple<pointer, D> as a data
> member.  The great thing about this solution is that it solves the
> empty member problem once and for all.
>

Excellant idea. I took a stab. I got this to work:

struct deleter { void operator()(int * p) { delete p; } };
int * i = new int;
tuple<int*,deleter> t(j,deleter());
static_assert(sizeof(t) == sizeof(int*),"");
get<1>(t)(get<0>(t));

However, EBO only kicks in when theres only one instance of each empty
type int the tuple (i.e. sizeof(tuple<deleter, deleter>) == 2 when I'd
like it to be 1).

I did something like this (same old type-traited class specialization
selection idiom i seem to always use):

template<int _Idx, typename _Head, bool _IsEmpty>
struct _Head_base;

template<int _Idx, typename _Head>
struct _Head_base<_Idx, _Head, true> : public _Head
{ _Head& _M_head() { return *static_cast<_Head*>(this); } ... };

template<int _Idx, typename _Head>
struct _Head_base<_Idx, _Head, false>
{ _Head& _M_head() {return _M_head_impl; } ... _Head _M_head_impl; };

template<int _Idx, typename _Head, typename... _Tail>
struct _Tuple_impl<_Idx, _Head, _Tail...>
: public _Tuple_impl<_Idx + 1, _Tail...>,
  private _Head_base<_Idx, _Head, is_empty<_Head>::value> {
typedef _Head_base<_Idx, _Head, std::is_empty<_Head>::value> _Base;
_Head& _M_head() { return _Base::_M_head(); }
...
};

Using inheritance again blows up with types that have virtual
overloads for _M_tail() and _M_head() accessors (violation of std of
course using underscore + capital letter).

I'm slightly stumped why ebo doesnt apply to tuple<empty,empty>. If I
follow the recursion (H = _Head_base, T = _Tuple_impl, => means
inherits from, comma separated bracket list) then:

tuple<A,A> => T<0,A,A> => [ T<1,A> => [ T<0>, H<1,A,true> => A ],
H<0,A,true> => A ]
vs.
tuple<A,B> => T<0,A,B> => [ T<1,B> => [ T<0>, H<1,B,true> => B ],
H<0,A,true> => A ]

Is it because T<0,A,A> has two paths to A and the ambiguity prevents EBO?
T<0,A,A> => H<0,A,true> => A
T<0,A,A> => T<1,A> => H<1,A,true> => A

Also, the following test case fails, haven't tracked down the specific
reason (feel free to enlighten me if you can!):
int i=0;
make_tuple(ref(i)) = tuple<int>(1);
assert(i == 1);

In member function '_Tuple_impl<_Idx, _Head, _Tail ...>&
_Tuple_impl<_Idx, _Head, _Tail ...>::operator=(const _Tuple_impl<_Idx,
_UElements ...>&) [with _UElements = int, int _Idx = 0, _Head =
std::reference_wrapper<int>, _Tail = ]':
tuple.hpp:183:   instantiated from 'tuple<_Elements>&
test::tuple<_Elements>::operator=(const tuple<_UElements ...>&) [with
_UElements = int, _Elements = std::reference_wrapper<int>]'
( 183 = static_cast<_Inherited&>(*this) = __in;)

tuple.hpp:146: error: no match for 'operator=' in '((_Tuple_impl<0,
std::reference_wrapper<int> >*)this)->_Tuple_impl<0,
std::reference_wrapper<int> >::<anonymous>._Head_base<_Idx, _Head,
false>::_M_head [with int _Idx = 0, _Head =
std::reference_wrapper<int>]() = ((const _Tuple_impl<0,
int>*)__in)->_Tuple_impl<_Idx, _Head, _Tail ...>::_M_head [with int
_Idx = 0, _Head = int, _Tail = ]()'
(146 = _Base::_M_head() = __in._M_head();)

Not sure if thats enough to discern the context in which the error occurs.

> Whether the std::committee will permit the empty member optimization
> on tuple or not, is another question I'm unsure of.  Though at the
> moment I don't think that this optimization is forbidden in the
> current working draft either.
>
> Also note LWG issue:
>
>    http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#673
>
> I have no idea at this point if these mods will make it into the
> standard.  But they are reflected in my reference implementation.
>
> -Howard
>
>
Cheers,
Chris


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]