Boost logo

Boost :

Subject: Re: [boost] Generic type inferencer function?
From: Paul Fultz II (pfultz2_at_[hidden])
Date: 2015-12-26 20:54:36


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. 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());

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`.

Paul

FIT_STATIC_FUNCTION(forward_as_tuple) =
fit::construct<std::tuple>().by(reference());

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.


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