Boost logo

Boost :

Subject: Re: [boost] [Tick] Universal quantified concepts/traits
From: pfultz2 (pfultz2_at_[hidden])
Date: 2015-01-06 13:48:42


> No, this trait has two parameters F and Wt. I'm looking for a trait with
> a single parameter W, the type constructor.

Ok I see, you mean that W is a templates.

> This SO question presents the same context.

Well that is one limitation. However, template members could be solved
either
by SFINAE-friendly lift operator or with reflection. However, what you are
trying to achieve is very difficult in C++ mainly due to template
specialization, function overloading, and substitution failure. Say we had a
simple function foo:

template<class T>
U foo(T);

Now, `foo` takes a T and returns U some other type. This is simple for the
compiler to follow, however, `foo` could return a type from a metafunction
like this:

template<class T>
typename some_metafunction<T>::type foo(T);

So with this, the compiler now has to trace each and every type `T`. Now
even
if thats possible, it doesn't even completely solve the problem. Next thing
is
the `w` template could have a constraint that only works for integrals:

template<class T, class=std::enable_if_c&lt;(std::is_integral&lt;T>())>>
class w;

So now if `foo` takes an `int` and returns `int`, but also takes a `long`
and
returns `std::vector<int>` then we have a problem. The map function could
work
correctly and map `w<T>` to `w<U>` however trying to map `w<long>` would be
a
compile error. So should this be considered a functor or not? Trying to
decide
whether its a functor in the general sense is difficult and its much better
to
decide on actual concrete or dependent types.

Of course, it is really useful to check your code in the more general sense
instead of relying on concrete type, so concepts can actually help solve
this
problem(the C++0x concepts, not the SFINAE concepts being currently
proposed).
So you could possibly write something like this:

template<template&lt;class...> class W>
concept Functor
{
    template<class F, class T, class
U=decltype(std::declval&lt;F>()(std::decval<T>()))>
    W<U> fmap(F f, W<T> w);
};

So the concept will ensure you are following the correct "interface", so if
you have a function that will use a `Functor` like this:

template<Functor W, class T, class F>
void apply(W<T> x, F f)
{
    fmap(f, x);
}

So the compiler will check that you are using a `Functor` in the template.
It
doesn't need to check every type(like when using SFINAE concepts). Then at
instantiation time the compiler will check that the concrete types meet the
requirements of the concept `Functor`.

Paul

--
View this message in context: http://boost.2283326.n4.nabble.com/Tick-Universal-quantified-concepts-traits-tp4670162p4670710.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

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