-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
how does one check to see whether a trait is true or false? #12
Comments
Suppose you have a trait defined like this: TICK_TRAIT(is_incrementable)
{
template<class T>
auto require(T&& x) -> valid<
decltype(x++),
decltype(++x)
>;
}; Then the trait can be checked like this with template<class T, TICK_REQUIRES(is_incrementable<T>())>
void increment(T& x)
{
x++;
} There is also macros for other forms such as lambdas and classes defined here: Template constraints. Furthermore, you can just check them directly using template<class T>
typename std::enable_if<(
is_incrementable<T>()
), int>::type
fun(const T & i) {
return ++i;
} Note, when I use |
On 1/30/16 7:16 AM, Paul Fultz II wrote:
One very confusing (to me) aspect of the documentation are the names EquallyComparable // equally comparable concept In your documentation and examples - you use is_equally_comparable for BCCL uses BOOST_CONCEPT_ASSERT((EquallyComparable)) to enforce a Concepts Lite uses EquallyComparable() to enforce a concept - I Soooo maybe the documenation would be easier to understand and more in line EquallyComparable() is either a constexpr bool or an integral_constant Then maybe the following would work template
and concept checking could be invoked with: static_assert<EquallyComparable(), "type requirement violation"); I confess that the syntax template<typename T, > is confusing For all I know, all this might well work already. I'll try it later. To The usability of constraint definition is less of concern as it's a much
-- Robert Ramey www.rrsd.com (805)569-3793 |
Yes that is correct.
The documentation needs to be updated to cleary show what gets defined by
In C++, traits to check concepts such as
You can do that already, as well as use template<class T>
void increment(T& x)
{
static_assert(is_incrementable<T>(), "Type requirements failed");
x++;
} However, if the user would like to use TICK_TRAIT(can_increment)
{
template<class T>
auto require(T&& x) -> valid<
decltype(increment(x))
>;
}; This trait will always be true, because
It should always be the last parameter. I will clarify that with the documentation. There is no problem with multiple parameters nor vardiac template parameters(if there were it would be documented). Secondly, type requirements are for template parameters, so it makes sense to define them with the template parameters.
That is the purpose of the macro: to abstract the ugly There is a pattern that needs to be followed, but it is a pretty simple pattern for the user to follow. It probably needs to be documented better, though. |
I'm still not getting this.
will trap at compiler time is T doesn't support the ++ operator. Right? But what do I do if I DON'T want it to trap - I just want the the
So will this trap or not? What do you recommend I use if I want a Robert Ramey |
I don't know what you mean by trap. The
|
On 1/31/16 2:59 PM, Paul Fultz II wrote:
template Will invoke a error at compile time if the type Cont doesn't fulfill the template<
Right? Now if we move down to section 2.2.1 Overloading of the same document I template<Associative_container C> So that the find function is called if and only if C fulfills the Robert Ramey |
Its important to understand that the compiler error comes from overload resolution failure. That is the compiler could not find an overload for the function that fulfills the requirement. That is why the error produced says Next, the compiler produces a note for each candidate function about why it failed. So in the concept-lite example is says
Well, first it is using the terse syntax. So it needs to be transformed to using the equivalent template<class C>
requires Associative_container<C>()
Iterator_type<C> find(C&& assoc, const Key_type<C>& key)
{
return assoc.find(key);
} Then from there we just rewrite it using template<class C, TICK_REQUIRES(Associative_container<C>())>
Iterator_type<C> find(C&& assoc, const Key_type<C>& key)
{
return assoc.find(key);
} This is almost equivalent. This is because the Tick library does not do subsuming of expressions. So in the example they give, if there was another overload for just ranges(in the paper they are relying on some new C++17 lookup rules): template<class R, class T, TICK_REQUIRES(Range<R>())>
Iterator_type<R> find(R&& r, const T& key)
{
return std::find(begin(r), end(r), key);
} Then we will have ambiguous overloads for template<class C>
Iterator_type<C> find_impl(C&& assoc, const Key_type<C>& key, tick::tag<tick::is_associative_container>)
{
return assoc.find(key);
}
template<class R, class T>
Iterator_type<R> find_impl(R&& r, const T& key, tick::tag<tick::is_range>)
{
using std::begin;
using std::end;
return std::find(begin(r), end(r), key);
}
template<class R, class T, TICK_REQUIRES(tick::is_range<R>())>
Iterator_type<R> find(R&& r, const T& key)
{
return find_impl(r, key, tick::most_refined<tick::is_associative_container<R>>());
} The second solution is to use FIT_STATIC_FUNCTION_LAMBDA(find) = fit::conditional(
[](auto&& assoc, const auto& key, TICK_PARAM_REQUIRES(tick::trait<is_associative_container>(assoc)))
{
assoc.find(key);
},
[](auto&& r, const auto& key, TICK_PARAM_REQUIRES(tick::trait<is_range>(r)))
{
using std::begin;
using std::end;
return std::find(begin(r), end(r), key);
}
); It is a little more compact, but of course is another dependency. |
On 1/31/16 4:00 PM, Paul Fultz II wrote:
If C doesn't not fulfill the requirements of an Associative_container, What am I missing here? Robert Ramey |
No, you get overload resolution failure, which turns into an error if it can't find another overload.
The overload is excluded. The problem with the example is there can be two overloads considered for Does that make sense? |
On 1/31/16 4:41 PM, Paul Fultz II wrote:
Going back to the original example TICK_TRAIT(is_incrementable) Then the trait can be checked like this with |TICK_REQUIRES|: template<class T, TICK_REQUIRES(is_incrementable())> If T doesn't support the ++ operator we get a compilation error with a But suppose I don't want the overload to be considered. If the I believe that this is what the concepts lite proposal assumes But I'm beginning to see that you might not agree these are Another confusion is between type requirements (aka concepts) boost::mpl::if_< It's not clear whether or not one can do this with TICK_TRAITS. Put I'm not trying to make your life difficult. I see you've invested I would also like the documentation to do more to "sell" type A side issue - I think DOxygen isn't very good a producing Robert Ramey -- Robert Ramey www.rrsd.com (805)569-3793 |
Thats not the error message you get. Rather the error message is
And thats the error you do get with
I am not sure I fully understand your different cases. Are you talking about the difference between using
Well these are boolean type traits, just like the type traits provided by the standard library or boost. They don't work anything like Boost.ConceptCheck library at all.
There is not that much magic going on here(as compared to Boost.ConceptCheck). The Then the
Yes the documentation needs to expand upon these things. Although it states these things, it perhaps is not the clearest for people who have used Boost.ConceptCheck which is very different from this library. I can see now how this can cause confusion. I think it will be a good idea if I write up an introduction for those coming from Boost.ConceptCheck.
The feedback is helpful, especially as I work toward improving the documentation.
There is a lot of work that needs to be done for the documentation. In fact, not everything has even been documented yet. All the traits in the
I don't use Doxygen anyways. |
OK - I'm back. Now I want to make a new trait. Looking at section "Getting Started" there is TICK_TRAIT(is_incrementable)
{
template<class T>
auto require(T&& x) -> valid<
decltype(x++),
decltype(++x)
>;
}; I don't see anywhere in the documentation where "require" or "valid" are described. It would seem that it's not possible for a naive user to discern how to create his own trait from looking at the documentation alone. I can probably try to analyze the code in the "build.h" header, but I don't think that's what you expect users to do. Also, the section Design Notes might benefit from a section - how the library is implemented. |
I'm looking this over to address a problem I have and I have a question. Suppose I've define the is_incrementable as you have in your first example. What I would like to do is something like
template
std::enable_if<
is_incrementable::value // syntax for this?
int
I'm expecting this is possible but I don't see it in the documentation. Please explain this to me.
Robert Ramey
The text was updated successfully, but these errors were encountered: