Topic: Policy Based Smart Ptr (n1681)


Author: dheld@codelogicconsulting.com ("David B. Held")
Date: Mon, 25 Oct 2004 18:21:52 GMT
Raw View
Vladimir Marko wrote:
> I've got two questions regarding the Policy Based
> Smart Ptr proposal (n1681).
>
> 1. Which policy covers the constness propagation?
> (In my opinion it is a crucial property of a smart
> pointer suitable for use in pimpl-idiom.)

Good question.  There has been much debate on the Boost mailing list
about whether smart pointers should propagate constness or not.  The
general consensus is that they should not, because raw pointers do
not, and in most cases, that is not what is desired.  I believe it
would be fairly easy to write a custom storage policy (call it
deep_const_storage, if you like) which does propagate constness.  I
will consider writing such a policy myself, if you do not volunteer
one first. ;)

> 2. Should the chained-policy approach illustration
> (page 4, similar on page 10) read
>
> template <typename T,
>           template<typename> class StoragePolicy,
>           template<typename> class OwnershipPolicy,
>           template<typename> class ConversionPolicy,
>           template<typename> class CheckingPolicy>
> class smart_ptr
>   : public
>       CheckingPolicy<
>         ConversionPolicy<
>           OwnershipPolicy<
>             StoragePolicy<T>
>           >
>         >
>       >
> { ... };
>
> instead of
>
> template <typename T,
>           class StoragePolicy,class OwnershipPolicy,
>           class ConversionPolicy,class CheckingPolicy>
> class smart_ptr
>   : public
>       CheckingPolicy<
>         ...
>       >
> { ... };

No.  The policies really are class types.  More specifically, to use
the terminology of Boost.MPL, they are "metafunction classes".  That
is, they are classes containing a metafunction named apply<> (which
"returns" a type named 'type').  This makes them very convenient to
use with MPL, and not much more difficult for policy writers to write.
This was especially important when support for template template
arguments was flaky across a large number of compilers.  Even though
support is decidedly better, it turns out that metafunction classes are
more flexible anyway (for instance, they are polymorphic w.r.t. template
arity), and the next version of MPL allegedly has built-in meta-lambda,
which means that it should also be possible to pass in lambda-ized
templates as well, without me having to modify the policy adaptor.  What
that means is that today, you can write:

smart_ptr<array_storage, assert_strict>::to<foo> p;

Because those are class types with nested template classes that do
the real work.  If you write your own policy, my_policy, you should
also write a metafunction class wrapper for it, and really do it like
so:

template <typename P>
class my_policy_
{
     // ...good stuff goes here
};

struct my_policy
{
     template <typename P>
     struct apply
     {
         typedef my_policy_<P> type;
     };
};

Then you will also be able to send in your policy even though
smart_ptr<> does not accept template template arguments:

smart_ptr<my_policy>::to<foo> q;

In the future, you should also be able to do this:

smart_ptr<my_policy_<_> >::to<foo> r;

This uses the meta-lambda facilities of MPL to allow you to pass
your raw template class through the policy adaptor without writing
a wrapper class (though I still prefer the wrapper).

Dave

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dheld@codelogicconsulting.com ("David B. Held")
Date: Mon, 25 Oct 2004 20:31:38 GMT
Raw View
Vladimir Marko wrote:

 > I've got two questions regarding the Policy Based
 > Smart Ptr proposal (n1681).
 >
 > 1. Which policy covers the constness propagation?
 > (In my opinion it is a crucial property of a smart
 > pointer suitable for use in pimpl-idiom.)


Good question.  There has been much debate on the Boost mailing list
about whether smart pointers should propagate constness or not.  The
general consensus is that they should not, because raw pointers do
not, and in most cases, that is not what is desired.  I believe it
would be fairly easy to write a custom storage policy (call it
deep_const_storage, if you like) which does propagate constness.  I
will consider writing such a policy myself, if you do not volunteer
one first. ;)

 > 2. Should the chained-policy approach illustration
 > (page 4, similar on page 10) read
 >
 > template <typename T,
 >           template<typename> class StoragePolicy,
 >           template<typename> class OwnershipPolicy,
 >           template<typename> class ConversionPolicy,
 >           template<typename> class CheckingPolicy>
 > class smart_ptr
 >   : public
 >       CheckingPolicy<
 >         ConversionPolicy<
 >           OwnershipPolicy<
 >             StoragePolicy<T>
 >           >
 >         >
 >       >
 > { ... };
 >
 > instead of
 >
 > template <typename T,
 >           class StoragePolicy,class OwnershipPolicy,
 >           class ConversionPolicy,class CheckingPolicy>
 > class smart_ptr
 >   : public
 >       CheckingPolicy<
 >         ...       >
 > { ... };


No.  The policies really are class types.  More specifically, to use
the terminology of Boost.MPL, they are "metafunction classes".  That
is, they are classes containing a metafunction named apply<> (which
"returns" a type named 'type').  This makes them very convenient to
use with MPL, and not much more difficult for policy writers to write.
This was especially important when support for template template
arguments was flaky across a large number of compilers.  Even though
support is decidedly better, it turns out that metafunction classes are
more flexible anyway (for instance, they are polymorphic w.r.t. template
arity), and the next version of MPL allegedly has built-in meta-lambda,
which means that it should also be possible to pass in lambda-ized
templates as well, without me having to modify the policy adaptor.  What
that means is that today, you can write:

smart_ptr<array_storage, assert_strict>::to<foo> p;

Because those are class types with nested template classes that do
the real work.  If you write your own policy, my_policy, you should
also write a metafunction class wrapper for it, and really do it like
so:

template <typename P>
class my_policy_
{
     // ...good stuff goes here
};

struct my_policy
{
     template <typename P>
     struct apply
     {
         typedef my_policy_<P> type;
     };
};

Then you will also be able to send in your policy even though
smart_ptr<> does not accept template template arguments:

smart_ptr<my_policy>::to<foo> q;

In the future, you should also be able to do this:

smart_ptr<my_policy_<_> >::to<foo> r;

This uses the meta-lambda facilities of MPL to allow you to pass
your raw template class through the policy adaptor without writing
a wrapper class (though I still prefer the wrapper).

Dave

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: swelef@post.sk (Vladimir Marko)
Date: Thu, 21 Oct 2004 01:55:49 GMT
Raw View
I've got two questions regarding the Policy Based
Smart Ptr proposal (n1681).

1. Which policy covers the constness propagation?
(In my opinion it is a crucial property of a smart
pointer suitable for use in pimpl-idiom.)

2. Should the chained-policy approach illustration
(page 4, similar on page 10) read

template <typename T,
          template<typename> class StoragePolicy,
          template<typename> class OwnershipPolicy,
          template<typename> class ConversionPolicy,
          template<typename> class CheckingPolicy>
class smart_ptr
  : public
      CheckingPolicy<
        ConversionPolicy<
          OwnershipPolicy<
            StoragePolicy<T>
          >
        >
      >
{ ... };

instead of

template <typename T,
          class StoragePolicy,class OwnershipPolicy,
          class ConversionPolicy,class CheckingPolicy>
class smart_ptr
  : public
      CheckingPolicy<
        ...
      >
{ ... };

?

Vladimir Marko

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]