|
Boost : |
Subject: Re: [boost] Generic type inferencer function?
From: Paul Fultz II (pfultz2_at_[hidden])
Date: 2016-01-04 10:53:58
On Tuesday, December 29, 2015 at 3:56:07 AM UTC-6, Vicente J. Botet Escriba
wrote:
>
> Le 27/12/2015 02:54, Paul Fultz II a écrit :
> >
> > On Friday, December 18, 2015 at 11:20:54 AM UTC-5, Nat Goodspeed wrote:
> >> Our code has any number of instances of this pattern:
> >>
> >> template <typename T, typename U>
> >> class SomeTemplate
> >> {
> >> SomeTemplate(const T& t, const U& u);
> >> ...
> >> };
> >>
> >> template <typename T, typename U>
> >> SomeTemplate<T, U> make_SomeTemplate(const T& t, const U& u)
> >> {
> >> return SomeTemplate<T, U>(t, u);
> >> }
> >>
> >> Am I overlooking a generic boost::make<something>() of this general
> form?
> >>
> >
> > This can easily be built using the `fit::construct` function from the
> Fit
> > library.
> There are some some specificities my make<> function has:
> * The template parameter can be a template class, a type
> constructor or a class
>
`fit::construct_meta` can be used with a metafunction or a metafunction
class.
> * The function is customizable
>
>
There is no need for customization. Rather `fit::construct` is used to
build
these functions.
> Can fit::construct<> be used like make<>?
>
Not exactly, rather it is a different approach to polymorphic constructors.
The `make<>` function tries to unify everything, and `fit::construct<>`
removes boilerplate for writing polymorphic constructors.
>
> > Plus, `by` can be used to apply prohejection to handle the
> > different
> > type of deductions necessary. Here's how to build `make` that decays
> each
> > parameter:
> >
> > FIT_STATIC_FUNCTION(make_tuple) =
> > fit::construct<std::tuple>().by(fit::decay);
> >
> > We can use `fit::decay` which will decay and unwrap references. For
> `tie`,
> > we
> > can do our own projection `lvalue`, which really does nothing except
> ensures
> > that lvalues are passed to the function:
> >
> > struct lvalue
> > {
> > template<class T>
> > constexpr T& operator()(T& x) const
> > {
> > return x;
> > }
> > };
> > FIT_STATIC_FUNCTION(tie) = fit::construct<std::tuple>().by(lvalue());
> >
> > The `forward_as_tuple` can also be written always deducing a reference:
> >
> > struct reference
> > {
> > template<class T>
> > constexpr T&& operator()(T&& x) const
> > {
> > return std::forward<T>(x);
> > }
> > };
> > FIT_STATIC_FUNCTION(forward_as_tuple) =
> > fit::construct<std::tuple>().by(reference());
> I don't know what the other think of having several ways to deduce the
> parameters.
>
Well its necessary in certain contexts, but it highly depends on the class.
Some classes may not have been written to support references or
rvalue references.
>
>
> > Of course, this can be used to create a generic factory. The problem
> with a
> > generic factory is some classes might want different ways of deducing
> the
> > parameters(perhaps the class doesn't allow for references at all). There
> > could
> > be some metaprogramming done to notify the generic factory, however, it
> > might be
> > easier just to write a custom factory(its only one line of code). So it
> > might be
> > better for the generic factory to have a customization point instead.
> >
> > Also, the three different factories provided by tuple seem to be a bad
> > choice
> > for the more general construction. It would be better to have three
> factory
> > type
> > functions like this:
> >
> > make - deduces lvalues as lvalues and rvalues as rvalues(ie it contains
> no
> > rvalue references)
> > make_forward - Everything is deduced as reference(like
> `forward_as_tuple`)
> > make_decay - decay the parameters and unwrap references(like
> `make_tuple`
> > and `make_pair`)
> >
> > Of course, this changes what people generally view `make` as. Perhaps a
> > different name could be used other than `make`.
> >
> >
> I people needs to make the difference I would prefer to have
>
> make: decay the parameters and unwrap references(like `make_tuple` and
> `make_pair`)
> forward_as: Everything is deduced as reference(like `forward_as_tuple`)
> ....
>
But you are missing the most important deduction which is deducing lvalues
as
lvalues and rvalues as rvalues. It currently is missing from standard C++,
but
it is very useful, and strikes the balance between mostly efficient and
mostly
safe. `make` is safe but not efficient, and `forward_as` is efficient but
not
always safe(rvalue references can easily lead to dangling references).
>
> Vicente
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk