Tick: Trait instrospection and concepts library now for C++11
Hi, I've just update the Tick library to support C++11 compilers including support for gcc 4.6: https://github.com/pfultz2/Tick To support gcc 4.6 an additional `TICK_RETURNS` macro was added. So while this can be written for gcc 4.7 or later: TICK_TRAIT(is_incrementable) { template<class T> auto requires_(T&& x) -> TICK_VALID( returns<int>(x++) ); }; This can be written in order to support gcc 4.6: TICK_TRAIT(is_incrementable) { template<class T> auto requires_(T&& x) -> TICK_VALID( TICK_RETURNS(x++, int) ); }; Of course, the macro is optional and only needed to support older compilers. Any other feedback would be appreciated. Thanks, Paul
Le 05/06/14 07:53, paul Fultz a écrit :
Hi,
I've just update the Tick library to support C++11 compilers including support for gcc 4.6:
https://github.com/pfultz2/Tick
To support gcc 4.6 an additional `TICK_RETURNS` macro was added. So while this can be written for gcc 4.7 or later:
TICK_TRAIT(is_incrementable) { template<class T> auto requires_(T&& x) -> TICK_VALID( returns<int>(x++) ); };
This can be written in order to support gcc 4.6:
TICK_TRAIT(is_incrementable) { template<class T> auto requires_(T&& x) -> TICK_VALID( TICK_RETURNS(x++, int) ); };
Of course, the macro is optional and only needed to support older compilers.
Any other feedback would be appreciated.
Hi, Does your library define just traits or try to emulate Concept Lite? In this post concepts@isocpp.org "[concepts] Can Concepts Lite be used to conditionally disable a copy constructor?" there are a couple of questions related to your library. * Can these traits be used to conditionally disable a constructors? an assignment? class NonCopyable { NonCopyable(NonCopyable const&) = delete; }; template <typename T> class wrapper { wrapper(const wrapper&) requires std::is_copy_constructible<T>::value {} }; * Can non-template members of template class be overloaded by only requires clause? I mean is the following examples correct (assuming that C1 and C2 are concepts): template<typename T> struct A { A(const A&) requires C1<T> { /*...*/ }; A(const A&) requires C2<T> { /*...*/ }; }; How the refinements plays on this concern? What are the limitations respect ConceptLite? Best, Vicente
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
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
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
Now, non-template members can be disabled, but they need to be made templated, like this:
template<class Base> struct A : Base { template
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/
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.
Yes, I have, however, tag dispatching doesn't work with
specialization(neither
does concept-based overloading, apparently). After thinking about it more, a
simpler way is to just use conditional overloading instead, which would work
something like this:
struct advance1
{
template
This is not a good idea. The default will be checked independently of whether increment is used or not, isn't it?
It gets checked when increment gets called(at instantiation). If `is_incrementable` is false, it will cause substitution failure. Paul -- View this message in context: http://boost.2283326.n4.nabble.com/Tick-Trait-instrospection-and-concepts-li... Sent from the Boost - Dev mailing list archive at Nabble.com.
participants (3)
-
paul Fultz
-
pfultz2
-
Vicente J. Botet Escriba