
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/