Boost logo

Boost :

Subject: Re: [boost] Tick: Trait instrospection library for C++14
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2014-05-31 19:53:49


Le 31/05/14 23:36, pfultz2 a écrit :
>> Ok, I can see the advantage of using macros, but please not too much.
> Yes, of course, that is the only macro that is required, and only because
> without it can be error prone(perhaps there is another way, but I am unaware
> of).
>
>> I like concept::models. tick_traits doesn't mean nothing significant.
> Yes, it probably would be better for me to use `models`.
>
>> Why do you need tick:ops?
> This will bring in the query operations(such as `returns`, `has_type`,
> `has_template`, etc), plus also the placholders(so you can just use
> `_`,`_1`,`_2`).
If the concept is defined in the namespace concepts this is not needed
as all these is also in the concepts namespace.
Maybe the user should not define its concepts in the same namespace.
>
>> I have the impression that the the underlying classes behind the macros
>> are more complex as it seems that they have been adapted so that tht
>> macros can generate the code.
> No, the classes and macros are really orthogonal. The only complexity added
> to
> the classes is that they store the base tratis and refinements so that you
> can
> see which of the base traits have failed. Which is completely unrelated to
> the
> macros.
I believe you "sur parolle".
What about needing to use placeholders when stating refinement?
Why do you need

TICK_TRAIT(is_x, is_Y<_>)

instead of

TICK_TRAIT(is_X, is_Y)

>
>> I really prefer the last one (even if the 42is magic). I need to admit
>> that the macro TICK_VALID could be useful.
> Except using just the `concepts::valid_expr` is problematic. If someone
> forgets to put in the hack(which is easy to do), it can lead to unintended
> compile errors. That is why the `TICK_VALID` macro is required.
I don't see the risk to be a valid reason to don't make it public and
documenting it. Let the user the choice to don't use macros please.
>
>> BTW, how do you know how many template parameters has the concept?
> That comes from how many parameters are used in the requires function.
Yes, but the macro needs to generate the is_trait class. Ah, I see it on
the code now, you have genrated a variadic template for any is_trait.

template<class... T> \
struct name \

I would prefer that the concept template had the good template members.
Could this be done?

|TICK_TRAIT(is_incrementable, T, refines,|||is_integral<_>|)|

>
>> Could a concept in your library have a non-type template parameter?
> It could, but behind scenes it would require wrapping it in a type. Athough,
> I
> could work on adding better support for non-type template parameters.
Isn't this a consequence of using macros?
>> No need for placeholders in Eric version.
> Actually, Eric does use placeholders as well, I'm not sure the reason.
Yes, I see them also.
> However, the reason I use placeholder expressions is better operability with
> current type traits. Eric's versions requires wrapping it in another class.
Yes, this allows you to write

|TICK_TRAIT(is_incrementable, std::is_integral<_>)|

>
> Also, another reason placeholders are used is overall simplicity. They are
> all
> type traits(ie `std::integral_constant<bool, B>` actually), and they work
> with
> other traits. The classes with the `requires` functions are just
> implementation details, this is to help avoid confusion about which class is
> to be used where. So, for example, if I want to refine the
> `is_incrementable`
> all I have to do is write `refines<is_incrementable&lt;_>>` whereas in
> Eric's
> version if I write `refines<Incrementble>` it could lead to a compile error.
> Where I should have written `refines<concepts::Incrementable>` instead.
This depends where your concept is defined. If it is defined in concepts
this works ;-)
You have the same namespace problem if the traits are defined in
different namespapces.
>
>> This FusionSequence concept is not completely necessary even if it could
>> be clearer. We need just
>>
>> struct SomeConcept
>> {
>> template<class T>
>> auto requires(T&& x) -> decltype(concepts::valid_expr(
>> concepts::is_true(boost::fusion::is_sequence<T>{})
>> ));
>> };
> This doesn't do the same thing. Perhaps its due to my poorly named example.
Agreed.
> It
> should be called `has_fusion_foo`, like this:
>
> TICK_TRAIT(has_fusion_foo)
> {
> template<class T>
> auto requires(T&& x) -> TICK_VALID(
> returns<boost::fusion::is_sequence&lt;_>>(x.foo())
> );
> };
Please could you explain what

returns<boost::fusion::is_sequence<_>>(x.foo())

checks? That there is a function member foo and ...

> Using Eric's framework:
>
> struct FusionSequence
> {
> template<class T>
> auto requires(T&& x) -> decltype(concepts::valid_expr(
> concepts::is_true(boost::fusion::is_sequence<T>{})
> ));
> };
>
> struct FusionFoo
> {
> template<class T>
> auto requires(T&& x) -> decltype(concepts::valid_expr(
> concept::model_of<FusionSequence>(x.foo())
> ));
> };
This check the function member foo returns a model of a Fusion sequence,
isn't it?
> template<class T>
> using has_fusion_foo = concept::model<T, FusionFoo>;
>
>>> Finally, I don't support adding nested types, like in the example you
>> gave
>>> with
>> Why?
> Its better to write it as a seperate trait, like this:
>
> template<typename T, typename U>
> using addable_result = boost::identity<decltype(std::declval&lt;T>() +
> std::declval<U>())>;
>
> This allows for better reusability and composability.
All good reasons, but as always is a taste question. Is there something
that prevents using them?
>
>> I prefer the concept::models<Concept, Model> expression to the trait
>> expression tick::trait<isConcept(Model)>.
> Maybe I might blend the two together and have
> `tick::models<Concept(Model)>`.
Why not.
>
>> I suggest you to provide a non-macro library that will be at least as
>> expressive as Eric's one and only on top of this expressive library add
>> some macros that make the user life easier.
> A non-macro version of the library is already provided with the exception of
> `TICK_VALID`. The only reason a non-macro version of `TICK_VALID` is not
> provided is because I feel it can be too error-prone.
See above.

Best,
Vicente


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