$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Aleksey Gurtovoy (agurtovoy_at_[hidden])
Date: 2002-10-09 02:57:53
David B. Held wrote:
> > Fixing a missing typename
>
> Technically, my version wasn't missing a typename, because I was using
> is_same<>::value with if_c. ;)
And I wasn't referring to that one :).
typedef typename mpl::if_c<
::boost::is_same<i_, mpl::end<Sequence>::type >::value,
^^^^^^^^^^^^^^^^^^^^^^^^
make_iterator<Default>, i_
>::type::type type;
>
> > and style a little bit, here's an "approved" version :)
>
> But I do like your version better. Thanks for the tip. I
> see that apply_if combines an if_ with a dereference, which happens
> to be the same as an apply. I wouldn't have figured that out on my own.
;)
http://www.mywikinet.com/mpl/#applyif, the last paragraph:
"The described technique is so common in template metaprograms, that it
makes sense to facilitate the selection of the nested type member by
introducing a high level equivalent to if_ that will do func_::type
operation as a part of its invocation. The MPL provides such a template -
it's called apply_if. ..."
> Now, I notice that you don't bother to hide "private metavariables",
> but just make everything struct. Is that simply because it would be silly
to
> try to use any of the the intermediate results, and thus there's no point
to
> try to hide any of the implementation details?
In the library code, I usually do hide auxiliary typedefs declared directly
in the scope of a public component:
template< typename T > struct my_algorithm
{
private:
typedef /* ... */ iter_;
typedef /* ... */ last_;
public:
typedef /* ... */ type;
};
to denote even more explicitly that members with '_' suffix do not comprise
a public interface. I usually don't bother with it in the scope of
implementation structs:
namespace aux {
template< typename T > struct my_impl
{
typedef /* ... */ iter_;
typedef /* ... */ last_;
typedef /* ... */ type;
};
}
// often defined in a separate header
template< typename T > struct my_algorithm
: aux::my_impl<T>
{
};
mostly because I am lazy ;).
>
> > [...]
> > A question - why BOOST_STORAGE_POLICY et al. instead of, let's say,
> >
> > typename get_storage_policy<policies_,T>::type
> >
> > ?
>
> Good question. Two reasons. One, repetition. They appear twice, and
> something as complex as this isn't something I want to spend time on
> synchronizing whenever I make a minor change (this is the
> kind of thing I'd spend an hour on diagnosing).
But from maintenance point of view the difference between
# define BOOST_STORAGE_POLICY \
apply_lambda< \
get_policy<policies_, storage_policy_tag, scalar_storage<_> >::type,
\
T \
>::type
...
class smart_ptr
: public optimally_inherit<
optimally_inherit<
BOOST_STORAGE_POLICY
...
{
public: // Policy types
typedef T element_type;
typedef BOOST_STORAGE_POLICY storage_policy;
and
namespace aux {
template< typename Policies, typename T >
struct storage_policy
{
typedef typename get_policy<
policies_
, storage_policy_tag
, scalar_storage<_>
>::type f_;
typedef typename apply_lambda<f_,T>::type type;
};
}
...
class smart_ptr
: public optimally_inherit<
optimally_inherit<
typename aux::storage_policy<policies_,T>::type
...
{
public: // Policy types
typedef T element_type;
typedef typename aux::storage_policy<policies_,T>::type
storage_policy;
is negligible, IMO (ignoring the fact that BOOST_STORAGE_POLICY is a macro
:).
> Two, what I didn't show is the template template version (which I left in
> for historical reasons).
> The usage is controlled by BOOST_SMART_POINTER_LEGACY_INTERFACE
OK, I see how that could warrant the existence of other macros besides
BOOST_SMART_POINTER_PARAMETERS. Thanks for elaborating.
[...]
> > [...]
> > Probably to have an associative container in MPL, but not
> > now :). Feel free to contribute, of course.
>
> Hmm...so if I understand correctly, I would add all the
> defaults to the container, then add the specified policies
> according to their categories, overwriting the default values.
> Then iterate over the container to get the final policies?
Yep, something like that. For instance,
namespace aux {
typedef mpl::map<
mpl::list<
scalar_storage<_>
, assert_check<_>
, ref_counted<_>
, disallow_conversion<_>
>
, get_category<_> // "key" function
> smart_ptr_default_params;
}
template<
typename DefaultParamsMap
, typename Params
>
struct params_map_gen
: mpl::fold<
Params
, DefaultParamsMap
, mpl::insert<_,_>
>
{
};
template <
typename T,
class P1 = empty_policy, class P2 = empty_policy,
class P3 = empty_policy, class P4 = empty_policy,
class params_map_ = typename params_map_gen<
aux::smart_ptr_default_params
, mpl::list<P1,P2,P3,P4>
>::type
>
class smart_ptr
: public optimally_inherit<
optimally_inherit<
typename aux::storage_policy<params_map_,T>::type
...
where 'storage_policy' is as simple as this:
template< typename PolicyMap, typename T >
struct storage_policy
{
typedef typename at<
PolicyMap
, storage_policy_tag
>::type f_;
typedef typename apply_lambda<f_,T>::type type;
};
> I might be able to hack a cheeseball metamap, though
> not a tree implementation (yet).
At this point I'm more interested in formulating an interface for
associative containers than their implementation qualities, so anything that
works will do.
Aleksey