Boost logo

Boost :

Subject: Re: [boost] Tick: Trait instrospection and concepts library now for C++11
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2014-06-07 04:28:12


Le 07/06/14 07:18, pfultz2 a écrit :
>> Does your library define just traits or try to emulate Concept Lite?
> I'm not quite sure what you are asking. The library doesn't do everything
> that
> Concepts Lite does. It lets you define concept-like predicates(commonly
> called a
> type trait in C++) in a similiar manner as Concepts Lite does. It does do
> template constraints as well, but this is just done using `enable_if`. Also,
> it
> won't resolve ambiguity between overloads like Concepts Lite does. However,
> I am
> thinking about implementing a mechanism for this. Perhaps something like
> this:
>
> struct advance1
> {
> template<class Iterator>
> TICK_OVERLOAD_REQUIRES(is_random_access_iterator<Iterator>);
>
> template<class Iterator>
> void operator()(Iterator& it, int n) const
> {
> it += n;
> }
>
> };
>
> struct advance2
> {
> template<class Iterator>
> TICK_OVERLOAD_REQUIRES(is_input_iterator<Iterator>);
>
> template<class Iterator>
> void operator()(Iterator& it, int n) const
> {
> while (n--) ++it;
> }
>
> };
>
> tick::overload<advance1, advance2> advance = {};
>
> However, this is fairly verbose even with the help of macros. It just might
> be
> easier to add some `not`s to the requires clause.
Have you read the Concept-Based Overloadingin Eric's blog [1]? Eric uses
a dispatching schema on which the Concept definition is the tag dispatcher.

// iterator_concept
template<typename T>
using iterator_concept =
concepts::most_refined<
typelist<
concepts::RandomAccessIterator,
concepts::BidirectionalIterator,
concepts::ForwardIterator,
concepts::InputIterator,
concepts::WeakInputIterator>, T>;
template<typename T>
using iterator_concept_t = meta_apply<iterator_concept, T>;

|// Random-access iterators go here|
|template||<||typename| |RndIt, ||typename| |Diff>|
|void| |advance_impl(RndIt & it, Diff d,|
|||ranges::concepts::RandomAccessIterator)|
|{|
|||it += d;|
|}|
|// All other iterator types go here|
|template||<||typename| |InIt, ||typename| |Diff>|
|void| |advance_impl(InIt & it, Diff d,|
|||ranges::concepts::InputIterator)|
|{|
|||for||(; d != 0; --d)|
|||++it;|
|}|
|template||<||typename| |InIt, ||typename| |Diff,|
|||CONCEPT_REQUIRES(ranges::InputIterator<InIt>() &&|
|||ranges::Integral<Diff>())>|
|void| |advance(InIt it, Diff d)|
|{|
|||advance_impl(it, d, ranges::iterator_concept_t<InIt>{});|
|}|

This is not perfect, but is the best we can do without concepts
integrated in the language.
What about adding this most_refined trait to your library? it would help
the user to do this tag dispatching?
> Now, non-template members can be disabled, but they need to be made
> templated,
> like this:
>
> template<class Base>
> struct A : Base
> {
> template<class Self=A, TICK_REQUIRES(is_incrementable<Self>())
> void increment()
> {
> ++(*this);
> }
> };
This is not a good idea. The default will be checked independently of
whether increment is used or not, isn't it?
> However, the library cannot be used with special members(such as copy
> constructors, move constructors, and assignment operators). This is a
> limitation
> of the language, since these special members cannont ever be templates.
I agree that this is a language limitation. The problem is not if they
are templates or not. The problem is when the constraints are checked.

> There
> might be a way to workaround the issue using universal references. I haven't
> really looked into it.
No, this is a real limitation.

Best,
Vicente.
[1] http://ericniebler.com/2013/11/23/concept-checking-in-c11/


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