[Review] Boost.Type Traits Extension by Frederic Bron

Dear All, This is the first day of the fast track review of Frédéric Bron's extensions to the Type Traits Library.This reviews will last until March 18th, 2011 under my management. All comments and reviews are very welcome. =========== What is it? =========== This extension adds 37 new traits corresponding to the following 37 operators: - binary: ==, !=,<,<=,>,>=, , +, -, *, /, %, +=, -=, *=, /=, %=, , &&, ||, ,&, |, ^,<<,>>,&=, |=, ^=,<<=,>>= - prefix: ++, --, +, -, !, ~, * - postfix: ++, -- Each trait can detect if the operator can be used with particular types and if needed, if the return type is convertible to some type. =================== Getting the library =================== The latest version can be downloaded by different ways: - from the vault with unix line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=type_traits.tar.bz2&directory=Extension& - from the vault with dos line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=type_traits-dos.tar.bz2&directory=Extension& - from the sandbox:http://svn.boost.org/svn/boost/sandbox/type_traits/ The entry point of the documentation is type_traits/libs/type_traits/doc/html/boost_typetraits/category/value_traits/operators.html The library has been tested with: - MSVC 8, 9, 10 on Windows, - g++ 4.4.5 on Linux, - intel 10.0 and 11.1 on Linux. To test the library, the simplest is to untar the headers in your boost include directory. For this, you can download the header part of the extension: - from the vault with unix line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=type_traits.headers_only.tar.bz2&directory=Extension& - from the vault with dos line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=type_traits.headers_only-dos.tar.bz2&directory=Extension&

Joel Falcou-3 wrote:
Dear All,
This is the first day of the fast track review of Frédéric Bron's extensions to the Type Traits Library.This reviews will last until March 18th, 2011 under my management. All comments and reviews are very welcome.
=========== What is it? ===========
This extension adds 37 new traits corresponding to the following 37 operators: - binary: ==, !=,<,<=,>,>=, , +, -, *, /, %, +=, -=, *=, /=, %=, , &&, ||, ,&, |, ^,<<,>>,&=, |=, ^=,<<=,>>= - prefix: ++, --, +, -, !, ~, * - postfix: ++, --
Each trait can detect if the operator can be used with particular types and if needed, if the return type is convertible to some type.
=================== Getting the library ===================
The latest version can be downloaded by different ways: - from the vault with unix line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=type_traits.tar.bz2&directory=Extension& - from the vault with dos line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=type_traits-dos.tar.bz2&directory=Extension& - from the sandbox:http://svn.boost.org/svn/boost/sandbox/type_traits/
The entry point of the documentation is type_traits/libs/type_traits/doc/html/boost_typetraits/category/value_traits/operators.html
Hi Joel, please could you provide a direct link to the documentation. I have tried http://svn.boost.org/svn/boost/sandbox/type_traits/libs/type_traits/doc/html... But it doesn't works completely (textual form only no html browsing). It is a shame that the reviewed extension doesn't have its own documentation and is mixed with the type_traits existing documentation. Thanks, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Monday, March 14, 2011 11:21:36 AM Vicente Botet wrote:
Joel Falcou-3 wrote:
Dear All,
This is the first day of the fast track review of Frédéric Bron's extensions to the Type Traits Library.This reviews will last until March 18th, 2011 under my management. All comments and reviews are very welcome.
=========== What is it? ===========
This extension adds 37 new traits corresponding to the following 37 operators: - binary: ==, !=,<,<=,>,>=, , +, -, *, /, %, +=, -=, *=, /=, %=, , &&, ||, ,&, |, ^,<<,>>,&=, |=, ^=,<<=,>>= - prefix: ++, --, +, -, !, ~, * - postfix: ++, --
Each trait can detect if the operator can be used with particular types and if needed, if the return type is convertible to some type.
=================== Getting the library ===================
The latest version can be downloaded by different ways: - from the vault with unix line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=ty pe_traits.tar.bz2&directory=Extension& - from the vault with dos line ending: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=ty pe_traits-dos.tar.bz2&directory=Extension& - from the sandbox:http://svn.boost.org/svn/boost/sandbox/type_traits/
The entry point of the documentation is type_traits/libs/type_traits/doc/html/boost_typetraits/category/value_t raits/operators.html
Hi Joel,
please could you provide a direct link to the documentation. I have tried
http://svn.boost.org/svn/boost/sandbox/type_traits/libs/type_traits/doc/h tml/boost_typetraits/category/value_traits/operators.html
But it doesn't works completely (textual form only no html browsing).
It is a shame that the reviewed extension doesn't have its own documentation and is mixed with the type_traits existing documentation.
The problem here is that the html files have the wrong svn mime-type property (text/plain), set it to text/html and the docs should be browsable directly from svn.
Thanks, Vicente

It is a shame that the reviewed extension doesn't have its own documentation and is mixed with the type_traits existing documentation.
If you just open the tarball you have the doc and there is a page just for the addition + links to each of the traits (type_traits/libs/type_traits/doc/html/boost_typetraits/category/value_traits/operators.html).
The problem here is that the html files have the wrong svn mime-type property (text/plain), set it to text/html and the docs should be browsable directly from svn.
I have changed that so that it now works better with the link you mentionned: http://svn.boost.org/svn/boost/sandbox/type_traits/libs/type_traits/doc/html... Note that you will not get the proper formatting. To get the proper formatting of the doc, you need to open the tarball. Frédéric

The default void return type should probably be changed to some internal dummy type. This would allow to check if the return type is actually void if so desired. class dymmy_type; template < class LHS, class RHS=LHS, class RET=dymmy_type> has_operator_op;

On 14.03.2011 16:27, Тимофей Игнатьич wrote:
The default void return type should probably be changed to some internal dummy type. This would allow to check if the return type is actually void if so desired.
class dymmy_type;
template< class LHS, class RHS=LHS, class RET=dymmy_type> has_operator_op;
i am agree with this. but *internal* sounds like: namespace boost { namespace type_traits { namespace detail { struct dymmy_type; } } template<class LHS, class RHS =LHS, class RET =type_traits::detail::dymmy_type>
has_operator_op;
} // namespace boost dummy_type should be placed in a "private" namespace

On 3/14/2011 9:53 AM, Max Sobolev wrote:
On 14.03.2011 16:27, Тимофей Игнатьич wrote:
The default void return type should probably be changed to some internal dummy type. This would allow to check if the return type is actually void if so desired.
class dymmy_type;
template< class LHS, class RHS=LHS, class RET=dymmy_type> has_operator_op;
i am agree with this.
but *internal* sounds like:
namespace boost {
namespace type_traits { namespace detail {
struct dymmy_type;
} }
template<class LHS, class RHS =LHS, class RET =type_traits::detail::dymmy_type>
has_operator_op;
} // namespace boost
dummy_type should be placed in a "private" namespace
What is a "private" namespace ?

On 3/14/2011 9:53 AM, Max Sobolev: dummy_type should be placed in a "private" namespace
Mon, 14 Mar 2011 11:43:00 -0400 Edward Diener <eldiener@tropicsoft.com> What is a "private" namespace ?
Оne that is not supposed to be accessed by the user. The language doesn't enforce this, hence the quotes.

On 3/14/2011 11:57 AM, Тимофей Игнатьич wrote:
On 3/14/2011 9:53 AM, Max Sobolev: dummy_type should be placed in a "private" namespace
Mon, 14 Mar 2011 11:43:00 -0400 Edward Diener<eldiener@tropicsoft.com> What is a "private" namespace ?
Оne that is not supposed to be accessed by the user. The language doesn't enforce this, hence the quotes.
Putting an identifier into boost::type_traits::detail seems pretty "private" to me since "detail" is never meant to be accessed by the end-user for any library. Is that what you were trying to suggest ? If so, i agree with you.
_______________________________________________ Unsubscribe& other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 14.03.2011 21:13, Edward Diener wrote:
On 3/14/2011 11:57 AM, Тимофей Игнатьич wrote:
On 3/14/2011 9:53 AM, Max Sobolev: dummy_type should be placed in a "private" namespace
Mon, 14 Mar 2011 11:43:00 -0400 Edward Diener<eldiener@tropicsoft.com> What is a "private" namespace ?
Оne that is not supposed to be accessed by the user. The language doesn't enforce this, hence the quotes.
Putting an identifier into boost::type_traits::detail seems pretty "private" to me since "detail" is never meant to be accessed by the end-user for any library. *Is that what you were trying to suggest ?*
yes In the old cool and famous *loki* library (by Andrei Alexandrescu) a similar namespace is named just *Private* :) -- - Do you speak English? Мужик с глубоким вздохом: - Yes I do. А хули толку?

The default void return type should probably be changed to some internal dummy type. This would allow to check if the return type is actually void if so desired.
class dymmy_type;
template < class LHS, class RHS=LHS, class RET=dymmy_type> has_operator_op;
I think your proposal seems reasonable and would improve the library. I will try to see if I can implement that. Frédéric

Frédéric Bron wrote:
The default void return type should probably be changed to some internal dummy type. This would allow to check if the return type is actually void if so desired.
class dymmy_type;
template < class LHS, class RHS=LHS, class RET=dymmy_type> has_operator_op;
I think your proposal seems reasonable and would improve the library. I will try to see if I can implement that.
Hi, are you saying that you can check if the return type is actually void? I believed that this was not possible, but who knows ... Or are you thinking on replacing the default RET value to specific class to say don't check the return type (e.g. dont_check), and generate acompile error when RET is void? Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

are you saying that you can check if the return type is actually void? I believed that this was not possible, but who knows ...
If you look at the implementation, I must separate implementation for operators returning void and operators returning non-void. So I know if the operator returns void or not: // this intermediate trait has member value of type bool: // - value==true -> operator- returns void // - value==false -> operator- does not return void template < typename RHS > struct operator_unary_minus_returns_void { // overloads of function returns_void make the difference // yes_type and no_type have different size by construction static ::boost::type_traits::yes_type returns_void(returns_void_t); static ::boost::type_traits::no_type returns_void(int); static const bool value=(sizeof(::boost::type_traits::yes_type)==sizeof(returns_void((-make<RHS>(),returns_void_t())))); }; So it seems that the best would be to have a default RET to do_no_check and having RET=void really checking if operator- returns void. Of course this needs checking... if it really works. Frédéric

Frédéric Bron wrote:
are you saying that you can check if the return type is actually void? I believed that this was not possible, but who knows ...
If you look at the implementation, I must separate implementation for operators returning void and operators returning non-void. So I know if the operator returns void or not:
// this intermediate trait has member value of type bool: // - value==true -> operator- returns void // - value==false -> operator- does not return void template < typename RHS > struct operator_unary_minus_returns_void { // overloads of function returns_void make the difference // yes_type and no_type have different size by construction static ::boost::type_traits::yes_type returns_void(returns_void_t); static ::boost::type_traits::no_type returns_void(int); static const bool value=(sizeof(::boost::type_traits::yes_type)==sizeof(returns_void((-make(),returns_void_t())))); };
I'm not sure this works. Guiven the operator-() overloading for any, the type of the expression (-make(),returns_void_t()) is always returns_void_t, isn't it? so the following expression would be always true sizeof(::boost::type_traits::yes_type)==sizeof(returns_void((-make(),returns_void_t()))) Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

Frédéric Bron wrote:
(-make(),returns_void_t()) is always returns_void_t, isn't it?
No because of this: template int operator,(T const &, returns_void_t);
I guess I understand it now how you check for RET void. I was not aware of this technique :(. Thanks, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

Frédéric Bron wrote:
So it seems that the best would be to have a default RET to do_no_check and having RET=void really checking if operator- returns void.
I think "ignore" or "dont_care" are better spellings of "do_no_check." _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 3/14/2011 6:27 AM, Тимофей Игнатьич wrote:
The default void return type should probably be changed to some internal dummy type. This would allow to check if the return type is actually void if so desired.
class dymmy_type;
template< class LHS, class RHS=LHS, class RET=dymmy_type> has_operator_op;
I actually prefer a "void" return type specified in the trait to mean that you're ignoring the return type of the operator. This is (more) consistent with the semantics of that template parameter when non-void. Checking that the return type is *precisely* void, to me, falls into the general category of checking that the return type satisfies some user-provided MPL metafunction. What about if you want to check if the return type is an rvalue or lvalue? Or a Proto expression? This is why I've been advocating for an extra template parameter to enable this capability for some time now. - Jeff

I actually prefer a "void" return type specified in the trait to mean that you're ignoring the return type of the operator. This is (more) consistent with the semantics of that template parameter when non-void.
Is it because for other types, it just checks for "convertible to" and not check for exact type? However, nothing can be converted to void apart from void so it would be still consistent to have RET=void checks for exact void return type.
Checking that the return type is *precisely* void, to me, falls into the general category of checking that the return type satisfies some user-provided MPL metafunction. What about if you want to check if the return type is an rvalue or lvalue? Or a Proto expression? This is why I've been advocating for an extra template parameter to enable this capability for some time now.
I understand you concern and I know you understood that it is beyond my competencies. Frédéric

Hi, Thanks Frédéric for proposing this waited for long time extension. if I have understood there is no mean to check if an operator or a function returns void. void has been used as default value for the RET type to don't check the return type, isn't it? If this is the case, this should be included in the limitations, as others could think that we can check for this, as other post let think. There is a declval function on Boost.Utility that creates a rvalue reference that could be used instead of the make() function. Please could you check if this function is adapted to your needs? The limitation related to the implicit conversion could maybe reduced if the traits take care of a special trait giving the list of classes that a class is implicitly convertible to implicitly_convertible_seq::type With this trait the has_operator_name traits could try to check before in this type sequence to avoid the ambiguity. The main problem is that this trait needs to be specialized for each class only once in a centralized way, which is quite restrictive. Of course this can be defined on top of the existing traits, so it is not a blocking issue for me, but I would like to know what other think of the approach. Just a last comment on the name of the structures used in the detail and specific namespace. Instead of repeating the name you could just use shorter names, e.g. namespace detail { namespace has_operator_unary_minus_impl { // ... // defines some typedef for convenience template < typename RHS, typename RET > struct has_operator_unary_minus_impl { typedef typename ::boost::remove_reference::type rhs_noref; typedef typename ::boost::remove_cv::type rhs_nocv; static const bool value=(has_operator_unary_minus_impl1 < rhs_noref, RET, ::boost::is_pointer< rhs_noref >::value >::value); }; } // namespace has_operator_unary_minus_impl } // namespace detail could be replaced by namespace detail { namespace has_operator_unary_minus_impl { // ... // defines some typedef for convenience template < typename RHS, typename RET > struct helper_0 { typedef typename remove_reference::type rhs_noref; typedef typename remove_cv::type rhs_nocv; static const bool value=(helper_1< rhs_noref, RET, is_pointer< rhs_noref
::value >::value); }; } // namespace has_operator_unary_minus_impl } // namespace detail
Last I agree that the use of equal should be replaced by assign when assignment is intended += has_operator_plus_equal -> has_operator_plus_assign -= has_operator_minus_equal -> has_operator_minus_assign Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

Hi again, some more naming comments: * shift operator could be named bit_left/right_shift * has_operator_complement could be has_operator_bit_not * prefix_ could be pre_ and suffix_ could be post_ (e.g. pre_increment and post_increment) BTW, could you in the documentation the list of operators that the library don't take care and why. I'm thinking to operators ',', '()', '&' (address), subscript . If I'm not wrong coma and address of could be implemented without issues and call and subscript operators could be implemented with some restrictions (" // The function call operator has to be a member function, so it can only be // detected for classes and unions by specialising this trait. It gives default // true for these. ") The original ConceptTraits library included also traits for default constructors and copy constructors, which have also limitations, but that the user could specialize. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

* shift operator could be named bit_left/right_shift
But this would let think that this operator operates only on integers which is wrong as it already operates with std::ostream std::istream from the standard library.
* has_operator_complement could be has_operator_bit_not
Same comment although there is no class from the standard library that defines this operator, right? but user classes could.
* prefix_ could be pre_ and suffix_ could be post_ (e.g. pre_increment and post_increment)
I have no issue with that.
BTW, could you in the documentation the list of operators that the library don't take care and why.
That is possible.
I'm thinking to operators ',', '()', '&' (address), subscript . If I'm not wrong coma and address of could be implemented without issues
I decided to implement all traits that share a similar implementation. ',', '&' do not behave as other operators because there is always a default operator for them. Therefore the implementation must be different. I am not saying it cannot be implemented but it is something different. I found already challenging to maintain these 37 operators with their specific behavior on fundamental types and pointers (in particular I wrote a long list of tests for all of them). Frédéric

Frédéric Bron wrote:
* shift operator could be named bit_left/right_shift
But this would let think that this operator operates only on integers which is wrong as it already operates with std::ostream std::istream from the standard library.
The std library overload the bitwise left/right shift operators for output/input purposes. The semantic has nothing to be with a (bit) shift operation. I don't see why removing the bit_ part will be clearer in this case.
* has_operator_complement could be has_operator_bit_not
Same comment although there is no class from the standard library that defines this operator, right? but user classes could.
For me &,|,^,~,<<,>> are bit operators and all should be named following the same schema.
I'm thinking to operators ',', '()', '&' (address), subscript . If I'm not wrong coma and address of could be implemented without issues
I decided to implement all traits that share a similar implementation. ',', '&' do not behave as other operators because there is always a default operator for them. Therefore the implementation must be different. I am not saying it cannot be implemented but it is something different. I found already challenging to maintain these 37 operators with their specific behavior on fundamental types and pointers (in particular I wrote a long list of tests for all of them).
I have not yet see the implementation and the tests (I will do it this evening), but in my opinion the logic of the 37 operators the library defines already is limited to binary operators, prefix unary operators and postfix unary operators. That mean that there are only 3 implementations to maintain, and the use of macros should do the rest. The same should apply for the tests. Write tests for the 3 kind of operators and use macros to test all the operators. I really would like to see the complete list of operators provided by the library, at least be as good as operators traits of Boost.ConceptsTraits/Operators is. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

I have not yet see the implementation and the tests (I will do it this evening), but in my opinion the logic of the 37 operators the library defines already is limited to binary operators, prefix unary operators and postfix unary operators. That mean that there are only 3 implementations to maintain, and the use of macros should do the rest.
The same should apply for the tests. Write tests for the 3 kind of operators and use macros to test all the operators.
Yes and no. Yes: the implementation uses only three different headers BUT some operations are forbidden by the standard. For example you cannot write: double x, y; x%y; This leads to compile time error. And every operator has its own rule of what is forbidden and what is not. Another example: assignement operators must have LHS be non const! I handle that with macros in the implementation FORBIDDEN_IF but in the tests, specific tests must be provided to ensure these specific behavior have been taken into account.
I really would like to see the complete list of operators provided by the library, at least be as good as operators traits of Boost.ConceptsTraits/Operators is.
I know... later maybe somebody can add the missing traits. Frédéric

Vicente Botet wrote:
For me &,|,^,~,<<,>> are bit operators and all should be named following the same schema.
Following a semantic naming convention, those are bitwise and, bitwise or, etc. Following a symbolic naming convention, those are ampersand, pipe, etc. The latter has the advantage of being independent of the types involved, allowing for their reinterpretation in various contexts, and, it would seem, leads to shorter names. However, consistency of naming, and allowances for non-English speakers (or at least non-native English speakers) should be made when considering the efficacy of the symbolic names. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 3/15/2011 1:46 AM, Frédéric Bron wrote:
* shift operator could be named bit_left/right_shift
But this would let think that this operator operates only on integers which is wrong as it already operates with std::ostream std::istream from the standard library.
I, too, prefer shift_left and shift_right, given their ubiquity related to std::iostream.
* has_operator_complement could be has_operator_bit_not
Same comment although there is no class from the standard library that defines this operator, right? but user classes could.
+1 for complement, although it's not a strong preference over bit_not.
* prefix_ could be pre_ and suffix_ could be post_ (e.g. pre_increment and post_increment)
I have no issue with that.
+1 for pre_increment etc. - Jeff

if I have understood there is no mean to check if an operator or a function returns void. void has been used as default value for the RET type to don't check the return type, isn't it?
You are right, void means "do not check" as stated in the documentation: "The default behaviour (RET=void) is to not check for the return value of binary operator+. Be careful that it does not mean that operator+ must return void to have the trait derive from true_type."
If this is the case, this should be included in the limitations, as others could think that we can check for this, as other post let think.
It is fair to add this in the known issues, even if it is already explained before.
There is a declval function on Boost.Utility that creates a rvalue reference that could be used instead of the make() function. Please could you check if this function is adapted to your needs?
Unfortunately I need a l-value, espacially for += type of operators.
The limitation related to the implicit conversion could maybe reduced if the traits take care of a special trait giving the list of classes that a class is implicitly convertible to
implicitly_convertible_seq::type
With this trait the has_operator_name traits could try to check before in this type sequence to avoid the ambiguity. The main problem is that this trait needs to be specialized for each class only once in a centralized way, which is quite restrictive. Of course this can be defined on top of the existing traits, so it is not a blocking issue for me, but I would like to know what other think of the approach.
I cannot comment on that as I do not see exactly how this would be implemented. Sorry.
Just a last comment on the name of the structures used in the detail and specific namespace. Instead of repeating the name you could just use shorter names, e.g.
You are right. I copied the structure of some other traits found in the type trait library. But as I am already in a detailed namespace (boost::detail::has_operator_unary_minus_impl), I can choose the same names for all operators inside these dedicated namespaces.
Last I agree that the use of equal should be replaced by assign when assignment is intended += has_operator_plus_equal -> has_operator_plus_assign -= has_operator_minus_equal -> has_operator_minus_assign
Why? is it to avoid confusion with "equal to"? I like plus_equal because plus is a sign and equal is also a sign. So I think it is easier to remember. Frédéric

Frédéric Bron wrote:
There is a declval function on Boost.Utility that creates a rvalue reference that could be used instead of the make() function. Please could you check if this function is adapted to your needs?
Unfortunately I need a l-value, espacially for += type of operators.
Oh, I see.
The limitation related to the implicit conversion could maybe reduced if the traits take care of a special trait giving the list of classes that a class is implicitly convertible to
implicitly_convertible_seq::type
With this trait the has_operator_name traits could try to check before in this type sequence to avoid the ambiguity. The main problem is that this trait needs to be specialized for each class only once in a centralized way, which is quite restrictive. Of course this can be defined on top of the existing traits, so it is not a blocking issue for me, but I would like to know what other think of the approach.
I cannot comment on that as I do not see exactly how this would be implemented. Sorry.
I will develop it later.
Last I agree that the use of equal should be replaced by assign when assignment is intended += has_operator_plus_equal -> has_operator_plus_assign -= has_operator_minus_equal -> has_operator_minus_assign
Why? is it to avoid confusion with "equal to"? I like plus_equal because plus is a sign and equal is also a sign. So I think it is easier to remember.
No, it is because the intended behavior on the builtin types is to make an assignment. Remember in C++ user defined types should follow the builtin semantics when possible. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

No, it is because the intended behavior on the builtin types is to make an assignment. Remember in C++ user defined types should follow the builtin semantics when possible.
I fully agree with that. operators should be as close as possible to what they do with built-in types. Is this still true for bitwise operators??? Frédéric

Vicente Botet wrote:
Frédéric Bron wrote:
Last I agree that the use of equal should be replaced by assign when assignment is intended += has_operator_plus_equal -> has_operator_plus_assign -= has_operator_minus_equal -> has_operator_minus_assign
Why? is it to avoid confusion with "equal to"? I like plus_equal because plus is a sign and equal is also a sign. So I think it is easier to remember.
No, it is because the intended behavior on the builtin types is to make an assignment. Remember in C++ user defined types should follow the builtin semantics when possible.
The "when possible" is a hint that such semantics are not always followed. There are legitimate cases in which a type has no relationship to built-in types, yet overloads operators. In such cases, the built-in semantics don't guide the naming of the operators. For example, the use of the left and right shift operators which, by the way, I never call "bit shift left" and "bit shift right" but just "left shift" and "right shift," are called the insertion and extraction operators in IOStreams. That augurs for naming the traits for the symbols rather than the semantics as Frédéric has done in this case so as to be more general. The question is whether all of the type traits names consistently follow the symbolic approach. If some are symbolic and others semantic, confusion is more likely. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Tue, Mar 15, 2011 at 12:04 PM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Vicente Botet wrote:
Frédéric Bron wrote:
Last I agree that the use of equal should be replaced by assign when assignment is intended += has_operator_plus_equal -> has_operator_plus_assign -= has_operator_minus_equal -> has_operator_minus_assign
Why? is it to avoid confusion with "equal to"? I like plus_equal because plus is a sign and equal is also a sign. So I think it is easier to remember.
No, it is because the intended behavior on the builtin types is to make an assignment. Remember in C++ user defined types should follow the builtin semantics when possible.
The "when possible" is a hint that such semantics are not always followed. There are legitimate cases in which a type has no relationship to built-in types, yet overloads operators. In such cases, the built-in semantics don't guide the naming of the operators. For example, the use of the left and right shift operators which, by the way, I never call "bit shift left" and "bit shift right" but just "left shift" and "right shift," are called the insertion and extraction operators in IOStreams. That augurs for naming the traits for the symbols rather than the semantics as Frédéric has done in this case so as to be more general.
The question is whether all of the type traits names consistently follow the symbolic approach. If some are symbolic and others semantic, confusion is more likely.
WRT naming i think we should strive for consistent naming in overall boost, not just the type_traits library. Proto, for example, names the operators as well, as does Boost.Operator. FWIW both libraries agree on left_shift/right_shift. Please take that into consideration.

Thomas Heller wrote:
WRT naming i think we should strive for consistent naming in overall boost, not just the type_traits library. Proto, for example, names the operators as well, as does Boost.Operator. FWIW both libraries agree on left_shift/right_shift.
Please take that into consideration.
+1 The following list of names from Proto looks quite good to me, and doesn't seem to contain any "odd sounding" names like "operator_plus_equal" <http://www.boost.org/doc/libs/1_46_1/doc/html/proto/users_guide.html#boost_proto.users_guide.intermediate_form.tags_and_metafunctions> Regards, Thomas

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Thomas Klimpel Sent: Tuesday, March 15, 2011 11:41 AM To: boost@lists.boost.org Subject: Re: [boost] [Review] Boost.Type Traits Extension by Frederic Bron
Thomas Heller wrote:
WRT naming i think we should strive for consistent naming in overall boost, not just the type_traits library. Proto, for example, names the operators as well, as does Boost.Operator. The following list of names from Proto looks quite good to me, and doesn't seem to contain any "odd sounding" names like "operator_plus_equal"
<http://www.boost.org/doc/libs/1_46_1/doc/html/proto/users_guide.html#bo ost_proto.users_guide.intermediate_form.tags_and_metafunctions>
There would seem to me to be a very strong case for having the same names as in Boost.Proto and Boost.Operator. Paul PS It is a bit disappointing not to have the icons and /images etc from the html and not to have a PDF version too? (The reference to the 'Printer friendly PDF' is to the current 'old' version). But I am sure this can be fixed eventually. --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

Paul A. Bristow-2 wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Thomas Klimpel Sent: Tuesday, March 15, 2011 11:41 AM To: boost@lists.boost.org Subject: Re: [boost] [Review] Boost.Type Traits Extension by Frederic Bron
Thomas Heller wrote:
WRT naming i think we should strive for consistent naming in overall boost, not just the type_traits library. Proto, for example, names the operators as well, as does Boost.Operator. The following list of names from Proto looks quite good to me, and doesn't seem to contain any "odd sounding" names like "operator_plus_equal"
<http://www.boost.org/doc/libs/1_46_1/doc/html/proto/users_guide.html#bo > ost_proto.users_guide.intermediate_form.tags_and_metafunctions>
There would seem to me to be a very strong case for having the same names as in Boost.Proto and Boost.Operator.
+1 Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

>> There would seem to me to be a very strong case for having the same names >> as >> in Boost.Proto and Boost.Operator. It would be difficult to have the same names as in Boost.Proto and Boost.Operator as they are different. However Boost.Proto seems to be the good candidates as it addresses all operators which is not the case for Boost.Operator. Also many names are already the same (see below). Frédéric type_traits Boost.Proto Boost.Operators binary == equal_to equal_to equality_comparable != not_equal_to not_equal_to < less less less_than_comparable <= less_equal less_equal > greater greater >= greater_equal greater_equal + plus plus - minus minus * multiplies multiplies / divides divides % modulus modulus += plus_equal plus_assign addable -= minus_equal minus_assign substractable *= multiplies_equal multiplies_assign multipliable /= divides_equal divides_assign dividable %= modulus_equal modulus_assign modable & bit_and bitwise_and | bit_or bitwise_or ^ bit_xor bitwise_xor &= bit_and_equal bitwise_and_assign andable |= bit_or_equal bitwise_or_assign orable ^= bit_xor_equal bitwise_xor_assign xorable << left_shift shift_left >> right_shift shift_right <<= left_shift_equal shift_left_assign left_shiftable >>= rifht_shift_equal shift_right_assign right_shiftable && logical_and logical_and || logical_or logical_or prefix + unary_plus unary_plus - unary_minus negate ~ complement complement ! logical_not logical_not * dereference dereference ++ prefix_increment pre_inc incrementable -- prefix_decrement pre_dec decrementable postfix ++ postfix_increment post_inc -- postfix_decrement post_dec

Frédéric Bron wrote: > > >> There would seem to me to be a very strong case for having > >> the same names as in Boost.Proto and Boost.Operator. > > It would be difficult to have the same names as in Boost.Proto > and Boost.Operator as they are different. However Boost.Proto > seems to be the good candidates as it addresses all operators > which is not the case for Boost.Operator. Also many names are > already the same (see below). +1 > type_traits Boost.Proto Boost.Operators binary > > == equal_to equal_to equality_comparable > != not_equal_to not_equal_to > < less less less_than_comparable > <= less_equal less_equal > > greater greater > >= greater_equal greater_equal > + plus plus > - minus minus > * multiplies multiplies > / divides divides > % modulus modulus > += plus_equal plus_assign addable Notice that "==" is about equality comparisons, so "equal" has to do with the operation rather than the symbol. Here, the operation is assignment (after addition), so "assign" is quite appropriate. By contrast, "plus" is about the symbol more than the operation. Thus, Proto's name is internally inconsistent. "add_assign" would be better. > -= minus_equal minus_assign substractable Ditto for "minus" versus "subtract." > *= multiplies_equal multiplies_assign multipliable I would prefer "multiply" to "multiplies," but it may be better to favor consistency with Proto. > /= divides_equal divides_assign dividable Ditto for "divide" versus "divides." > %= modulus_equal modulus_assign modable > & bit_and bitwise_and > | bit_or bitwise_or > ^ bit_xor bitwise_xor > &= bit_and_equal bitwise_and_assign andable > |= bit_or_equal bitwise_or_assign orable > ^= bit_xor_equal bitwise_xor_assign xorable FWIW, I always use "bitwise" rather than "bit" when I verbalize those operators. > << left_shift shift_left > >> right_shift shift_right > <<= left_shift_equal shift_left_assign left_shiftable > >>= right_shift_equal shift_right_assign right_shiftable I find direction + "shift" the better order, but consistency with Proto might be the better thing. > && logical_and logical_and > || logical_or logical_or prefix > + unary_plus unary_plus > - unary_minus negate An odd inconsistency in Proto, unless "negate" was actually from Operators. > ~ complement complement > ! logical_not logical_not > * dereference dereference > ++ prefix_increment pre_inc incrementable > -- prefix_decrement pre_dec decrementable postfix > ++ postfix_increment post_inc > -- postfix_decrement post_dec I generally like the names from Proto. Consistency would be nice, but consider the names as they are likely to be standardized. Better to get the names "right" now. For example, I think "postfix_increment" is a likely name for standardization, while "post_inc" is not. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 16/03/11 13:11, Stewart, Robert wrote:
I generally like the names from Proto. Consistency would be nice, but consider the names as they are likely to be standardized. Better to get the names "right" now. For example, I think "postfix_increment" is a likely name for standardization, while "post_inc" is not.
I guess some typedef could be done so we have a consistent proto list of operator's name. I found myself stumbling upon unary_minus vs negate a lot of time, especially because for me negate is always this strange libm binary function that transfer sign of a over b. Renaming them in proto may break code I guess, but i dont think adding a typedef do any harm. Eric ?

Joel Falcou-3 wrote:
On 16/03/11 13:11, Stewart, Robert wrote:
I generally like the names from Proto. Consistency would be nice, but consider the names as they are likely to be standardized. Better to get the names "right" now. For example, I think "postfix_increment" is a likely name for standardization, while "post_inc" is not.
I guess some typedef could be done so we have a consistent proto list of operator's name.
+1 Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

Stewart, Robert wrote: > > Frédéric Bron wrote: >> >> >> There would seem to me to be a very strong case for having >> >> the same names as in Boost.Proto and Boost.Operator. >> >> It would be difficult to have the same names as in Boost.Proto >> and Boost.Operator as they are different. However Boost.Proto >> seems to be the good candidates as it addresses all operators >> which is not the case for Boost.Operator. Also many names are >> already the same (see below). > > +1 > >> type_traits Boost.Proto Boost.Operators binary >> >> == equal_to equal_to equality_comparable >> != not_equal_to not_equal_to >> < less less less_than_comparable >> <= less_equal less_equal >> > greater greater >> >= greater_equal greater_equal >> + plus plus >> - minus minus >> * multiplies multiplies >> / divides divides >> % modulus modulus >> += plus_equal plus_assign addable > Please do not mix operators and concepts (equality_comparable, addable, less_than_comparable) which are adjectives. > Notice that "==" is about equality comparisons, so "equal" has to do with > the operation rather than the symbol. Here, the operation is assignment > (after addition), so "assign" is quite appropriate. > > By contrast, "plus" is about the symbol more than the operation. Thus, > Proto's name is internally inconsistent. "add_assign" would be better. > >> -= minus_equal minus_assign substractable > > Ditto for "minus" versus "subtract." > >> *= multiplies_equal multiplies_assign multipliable > > I would prefer "multiply" to "multiplies," but it may be better to favor > consistency with Proto. > >> /= divides_equal divides_assign dividable > > Ditto for "divide" versus "divides." > std::ratio uses add, subtract, multiply and divide, this corresponds to verbs not to nouns and have a semantic associated. Not also that we have Boost.MPL which has also some names for arithmetic operators. It uses plus,minus,times and divides. I think that that the names we are looking for should be names. > >> %= modulus_equal modulus_assign modable >> & bit_and bitwise_and >> | bit_or bitwise_or >> ^ bit_xor bitwise_xor >> &= bit_and_equal bitwise_and_assign andable >> |= bit_or_equal bitwise_or_assign orable >> ^= bit_xor_equal bitwise_xor_assign xorable > > FWIW, I always use "bitwise" rather than "bit" when I verbalize those > operators. > +1 >> << left_shift shift_left >> >> right_shift shift_right >> <<= left_shift_equal shift_left_assign left_shiftable >> >>= right_shift_equal shift_right_assign right_shiftable > > I find direction + "shift" the better order, but consistency with Proto > might be the better thing. > +1 for direction + "shift" >> && logical_and logical_and >> || logical_or logical_or prefix >> + unary_plus unary_plus >> - unary_minus negate > > An odd inconsistency in Proto, unless "negate" was actually from > Operators. > > I generally like the names from Proto. Consistency would be nice, but > consider the names as they are likely to be standardized. Better to get > the names "right" now. For example, I think "postfix_increment" is a > likely name for standardization, while "post_inc" is not. > > "postfix_increment" is already in use on the standard: "Increment and decrement [over.inc] 1 The user-defined function called operator++ implements the prefix and postfix ++ operator. If this function is a member function with no parameters, or a non-member function with one parameter of class or enumeration type, it defines the prefix increment operator ++ for objects of that type. If the function is a member function with one parameter (which shall be of type int) or a non-member function with two parameters (the second of which shall be of type int), it defines the postfix increment operator ++ for objects of that type. When the postfix increment is called as a result of using the ++ operator, the int argument will have value zero." pre-increment and post-increment are also already used in the standard. E.g. "raw_storage_iterator<OutputIterator,T>& operator++() noexcept; Effects: Pre-increment: advances the iterator and returns a reference to the updated iterator. raw_storage_iterator<OutputIterator,T> operator++(int) noexcept; Effects: Post-increment: advances the iterator and returns the old value of the iterator." "post- increment operator (operator++)." Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Frederic-Bron-tp3353283p3381645.html Sent from the Boost - Dev mailing list archive at Nabble.com.

Vicente Botet wrote:
Frédéric Bron wrote:
The limitation related to the implicit conversion could maybe be reduced if the traits take care of a special trait giving the list of classes that a class is implicitly convertible to
implicitly_convertible_seq::type
With this trait the has_operator_name traits could try to check before in this type sequence to avoid the ambiguity. The main problem is that this trait needs to be specialized for each class only once in a centralized way, which is quite restrictive. Of course this can be defined on top of the existing traits, so it is not a blocking issue for me, but I would like to know what other think of the approach.
I cannot comment on that as I do not see exactly how this would be implemented. Sorry.
I will develop it later.
From the documentation " * There is an issue if the operator exists only for type A and B is convertible to A. In this case, the compiler will report an ambigous overload because both the existing operator and the one we provide (with argument of type any) need type conversion, so that none is preferred. "
Given the trait template struct implicitly_convertible_seq { typedef mpl::vector0<> type; }; which must be specialized explicitly for each type having implicit conversions. We can define on to of the existing interface a trait that takes care of implicit conversions template struct has_operator_unary_minus_ext { // in pseudo imperative code FOREACH t in implicitly_convertible_seq::type if has_operator_unary_minus<RHS, t>::value then typedef true_type type; return; endif typedef has_operator_unary_minus<RHS, RET> type; }; To take care of the examples in the doc we will do struct A { }; void operator-(const A&); struct B { operator A(); }; template <> struct implicitly_convertible_seq { typedef mpl::vector type; }; boost::has_operator_unary_minus ::value; // this is fine boost::has_operator_unary_minus::value; // No error: as class A is in the list of conversion from B, so boost::has_operator_unary_minus ::value is tested before Let me know if you need some explanations. Best, Vicente Typo: replace ambigous by ambiguous in the doc. -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

On 3/15/2011 6:37 PM, Vicente Botet wrote:
Vicente Botet wrote:
Frédéric Bron wrote:
The limitation related to the implicit conversion could maybe be reduced if the traits take care of a special trait giving the list of classes that a class is implicitly convertible to
implicitly_convertible_seq::type
With this trait the has_operator_name traits could try to check before in this type sequence to avoid the ambiguity. The main problem is that this trait needs to be specialized for each class only once in a centralized way, which is quite restrictive. Of course this can be defined on top of the existing traits, so it is not a blocking issue for me, but I would like to know what other think of the approach.
I cannot comment on that as I do not see exactly how this would be implemented. Sorry.
I will develop it later.
From the documentation " * There is an issue if the operator exists only for type A and B is convertible to A. In this case, the compiler will report an ambigous overload because both the existing operator and the one we provide (with argument of type any) need type conversion, so that none is preferred. "
Given the trait
template struct implicitly_convertible_seq { typedef mpl::vector0<> type; };
which must be specialized explicitly for each type having implicit conversions. We can define on to of the existing interface a trait that takes care of implicit conversions
template struct has_operator_unary_minus_ext { // in pseudo imperative code
FOREACH t in implicitly_convertible_seq::type if has_operator_unary_minus<RHS, t>::value then typedef true_type type; return; endif typedef has_operator_unary_minus<RHS, RET> type; };
To take care of the examples in the doc we will do
struct A { }; void operator-(const A&); struct B { operator A(); }; template<> struct implicitly_convertible_seq { typedef mpl::vector type; }; boost::has_operator_unary_minus ::value; // this is fine boost::has_operator_unary_minus::value; // No error: as class A is in the list of conversion from B, so boost::has_operator_unary_minus ::value is tested before
Let me know if you need some explanations.
This idea looks promising but it would be even more so if your '<' was not showing as '<' and you '>' was not showing as '>' everywhere in your messages so I could follow it more easily. I do understand what you are saying, and it offers a decent workaround even at the price og an end-user of a type doing a little more work. I too am very interested if the "Known Issues" which can cause compiler errors when using type traits operators can be solved. or worked around, without causing compiler errors.

On 3/15/2011 1:38 AM, Frédéric Bron wrote: [...]
There is a declval function on Boost.Utility that creates a rvalue reference that could be used instead of the make() function. Please could you check if this function is adapted to your needs?
Unfortunately I need a l-value, espacially for += type of operators.
declval should give you an lvalue if you give it a (lvalue-) reference type, e.g., declval< T& >() where T is a non-reference type... [...]
Last I agree that the use of equal should be replaced by assign when assignment is intended += has_operator_plus_equal -> has_operator_plus_assign -= has_operator_minus_equal -> has_operator_minus_assign
Why? is it to avoid confusion with "equal to"? I like plus_equal because plus is a sign and equal is also a sign. So I think it is easier to remember.
I prefer op_equal as well, but it's not a strong preference. - Jeff

Hi, The following two types are not used anywhere typedef typename ::boost::remove_cv::type rhs_nocv; typedef typename ::boost::remove_cv< typename ::boost::remove_reference< typename ::boost::remove_pointer::type >::type >::type rhs_noptr; Shouldn't them be removed? I have not see the utility of removing the reference typedef typename ::boost::remove_reference::type rhs_noref; Could you explain me why this is needed? I have a little problem with the has_operator_ prefix on the name of the traits. The traits is not checking the class parameter(s) has/have an operator, but that the application of the operator to this/these types is syntactically correct. E.g. has_operator_plus<int, double>::value neither int nor double have an operator+. applicable_operator_plus<int, double>::value or can_apply_operator_plus could be an option. If we wanted to define a trait to see if a class has a member function begin(), i.e. c.begin() is correct, we could name it has_begin. But if we wanted to check if we can call begin(c) how we name the trait, has_begin? Note that in the standard all the traits prefixed by has_ applies to some property the type has. I recognize that this is not to important, but if someone could find a better name ... Forget this last comment if you find it is misplaced. Best, Vicente P.S. Typo: There is at least a BOOST_TT_TRAIT_OP in the documentation to be replaced by -. -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

On 3/15/2011 6:48 PM, Vicente Botet wrote:
Hi,
The following two types are not used anywhere typedef typename ::boost::remove_cv::type rhs_nocv; typedef typename ::boost::remove_cv< typename ::boost::remove_reference< typename ::boost::remove_pointer::type>::type>::type rhs_noptr;
Shouldn't them be removed?
I have not see the utility of removing the reference typedef typename ::boost::remove_reference::type rhs_noref;
Could you explain me why this is needed?
I have a little problem with the has_operator_ prefix on the name of the traits. The traits is not checking the class parameter(s) has/have an operator, but that the application of the operator to this/these types is syntactically correct. E.g. has_operator_plus<int, double>::value neither int nor double have an operator+. applicable_operator_plus<int, double>::value or can_apply_operator_plus could be an option.
If we wanted to define a trait to see if a class has a member function begin(), i.e. c.begin() is correct, we could name it has_begin.
In TTI it becomes boost::tti::has_member_function_begin using the simple form of the macro expansion.
But if we wanted to check if we can call begin(c) how we name the trait, has_begin?
I would think that 'has_function_begin' would distinguish it nicely.
Note that in the standard all the traits prefixed by has_ applies to some property the type has. I recognize that this is not to important, but if someone could find a better name ... Forget this last comment if you find it is misplaced.
I think 'has_' is fine.

The following two types are not used anywhere typedef typename ::boost::remove_cv::type rhs_nocv; typedef typename ::boost::remove_cv< typename ::boost::remove_reference< typename ::boost::remove_pointer::type >::type >::type rhs_noptr;
Shouldn't them be removed?
They are used, but not in the example of the doc. These shortcuts are used extensively in the macro FOBIDDEN_IF which determines if the operator is forbidden for fundamental types (to avoid compile time error). In the doc, I chose a simple case (unary_minus) where FORBIDDEN_IF is only ::boost::is_pointer< rhs_noref >::value Here is a more complex example (has_operator_plus.hpp): #define BOOST_TT_FORBIDDEN_IF\ ::boost::type_traits::ice_or<\ /* pointer with pointer */\ ::boost::type_traits::ice_and<\ ::boost::is_pointer< lhs_noref >::value,\ ::boost::is_pointer< rhs_noref >::value\ >::value,\ /* pointer with fundamental non integral */\ ::boost::type_traits::ice_and<\ ::boost::is_pointer< lhs_noref >::value,\ ::boost::is_fundamental< rhs_nocv >::value,\ ::boost::type_traits::ice_not< ::boost::is_integral< rhs_noref >::value >::value\ >::value,\ ::boost::type_traits::ice_and<\ ::boost::is_pointer< rhs_noref >::value,\ ::boost::is_fundamental< lhs_nocv >::value,\ ::boost::type_traits::ice_not< ::boost::is_integral< lhs_noref >::value >::value\ >::value,\ /* void* with fundamental */\ ::boost::type_traits::ice_and<\ ::boost::is_pointer< lhs_noref >::value,\ ::boost::is_void< lhs_noptr >::value,\ ::boost::is_fundamental< rhs_nocv >::value\ >::value,\ ::boost::type_traits::ice_and<\ ::boost::is_pointer< rhs_noref >::value,\ ::boost::is_void< rhs_noptr >::value,\ ::boost::is_fundamental< lhs_nocv >::value\ >::value\
::value
I have not see the utility of removing the reference typedef typename ::boost::remove_reference::type rhs_noref;
It is just used to know if the operation is forbidden for fundamental types and pointers. It avoids having everywhere typename ::boost::remove_reference< ... >::type. When checking for existence of operator, full type qualification is used (i.e. LHS or RHS). Frédéric

On 3/14/2011 12:48 AM, Joel Falcou wrote:
Dear All,
This is the first day of the fast track review of Frédéric Bron's extensions to the Type Traits Library.This reviews will last until March 18th, 2011 under my management. All comments and reviews are very welcome. [...]
(Review to come eventually...) I'm browsing the source, and don't see a lot of difference between detail/has_postfix_operator.hpp and detail/has_prefix_operator.hpp. Frederic (excuse the lack of accents), are the only differences the operator overload declaration and the location of BOOST_TT_TRAIT_OP relative to make<LHS>() or make<RHS>()? If so, for maintenance purposes, it may be wise to combine the 2 headers. What is the community's feeling about adding a 3rd template parameter (or some other equivalent interface) to constrain the result type of the operator other than "is convertible to"? E.g., I've proposed adding the ability to pass a Boost.MPL metafunction to evaluate on the result type of the operation. One could use some other mechanism if one doesn't wish to couple Boost.TypeTraits to Boost.MPL. I'm motivated by the fact that, although checking convertibility seems like the most common use case (and the current interface is what I'd expect it to look like), one may want to constrain the result type further. For example, checking for an exact type match, or checking for rvalueness/lvalueness. I'd be willing to help add this capability, but if there is little or no support for it, then it needn't be further pursued. - Jeff

I'm browsing the source, and don't see a lot of difference between detail/has_postfix_operator.hpp and detail/has_prefix_operator.hpp. Frederic (excuse the lack of accents), are the only differences the operator overload declaration and the location of BOOST_TT_TRAIT_OP relative to make<LHS>() or make<RHS>()? If so, for maintenance purposes, it may be wise to combine the 2 headers.
Yes they are very similar but there another difference: postfix operators have an additional int argument in their declaration so that combining may be a bit tricky. Frédéric

[Frederic, for some reason, when I hit "reply" in Thunderbird on your emails, they get addressed to you and not to the list. I also see that I am cc'ed on your replies to my list emails, which, as far as I know, doesn't normally happen. Do you have any idea if the problem is on your end or my end?] On 3/16/2011 11:57 AM, Frédéric Bron wrote:
I'm browsing the source, and don't see a lot of difference between detail/has_postfix_operator.hpp and detail/has_prefix_operator.hpp. Frederic (excuse the lack of accents), are the only differences the operator overload declaration and the location of BOOST_TT_TRAIT_OP relative to make<LHS>() or make<RHS>()? If so, for maintenance purposes, it may be wise to combine the 2 headers.
Yes they are very similar but there another difference: postfix operators have an additional int argument in their declaration so that combining may be a bit tricky.
I thought I accounted for that with "the operator overload declaration"... Anyways, it sounds like you'd have to parameterize the overload declaration as well as the operator application (and that's it...?). Whether this is worth the trouble is up to you. It's just a suggestion to, again, simplify maintenance. - Jeff

I thought I accounted for that with "the operator overload declaration"...
Sorry, missed that!
Anyways, it sounds like you'd have to parameterize the overload declaration as well as the operator application (and that's it...?). Whether this is worth the trouble is up to you. It's just a suggestion to, again, simplify maintenance.
I will probably stick to 3 files. I use vimdiff when I change one so that I can change the others the same. I is not really a pain. Thanks, Frédéric

On 3/16/2011 2:49 PM, Jeffrey Lee Hellrung, Jr. wrote:
On 3/14/2011 12:48 AM, Joel Falcou wrote:
Dear All,
This is the first day of the fast track review of Frédéric Bron's extensions to the Type Traits Library.This reviews will last until March 18th, 2011 under my management. All comments and reviews are very welcome. What is the community's feeling about adding a 3rd template parameter (or some other equivalent interface) to constrain the result type of the operator other than "is convertible to"? E.g., I've proposed adding the ability to pass a Boost.MPL metafunction to evaluate on the result type of the operation. One could use some other mechanism if one doesn't wish to couple Boost.TypeTraits to Boost.MPL. I'm motivated by the fact that, although checking convertibility seems like the most common use case (and the current interface is what I'd expect it to look like), one may want to constrain the result type further. For example, checking for an exact type match, or checking for rvalueness/lvalueness.
I'd be willing to help add this capability, but if there is little or no support for it, then it needn't be further pursued.
I think you are overdoing and overcomplicating what is necessary.

2011/3/14 Joel Falcou <joel.falcou@lri.fr>:
Dear All,
This is the first day of the fast track review of Frédéric Bron's extensions to the Type Traits Library.This reviews will last until March 18th, 2011 [...]
Hi Frédéric, thank you again for implementing this has_operator extension. I've found some problems. In the ICL I have an operator + template <class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const typename Type::value_type& operand); and is seems that more overloads are checked valid as actually exist. Is this intentional? BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT; // This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value)); // These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); } Regards, Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

2011/3/17 Joachim Faulhaber <afojgo@googlemail.com>:
2011/3/14 Joel Falcou <joel.falcou@lri.fr>:
Dear All,
This is the first day of the fast track review of Frédéric Bron's extensions to the Type Traits Library.This reviews will last until March 18th, 2011 [...]
Hi Frédéric,
thank you again for implementing this has_operator extension. I've found some problems. In the ICL I have an operator +
template <class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const typename Type::value_type& operand);
correction the operator is declared: template <class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const Type& operand);
and is seems that more overloads are checked valid as actually exist. Is this intentional?
BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT;
// This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value));
BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value));
// These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); }
Regards, Joachim
-- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

On 3/17/2011 7:17 AM, Joachim Faulhaber wrote:
2011/3/17 Joachim Faulhaber<afojgo@googlemail.com>: [...]
thank you again for implementing this has_operator extension. I've found some problems. In the ICL I have an operator + [...] template<class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const Type& operand);
and is seems that more overloads are checked valid as actually exist. Is this intentional?
BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT;
// This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value));
BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value));
// These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); }
An operator trait allows implicit conversions in the arguments. In fact, the current implementation strategy *must* allow implicit conversions in the arguments, i.e., I wouldn't know how to detect *exact* signatures. - Jeff

2011/3/17 Jeffrey Lee Hellrung, Jr. <jhellrung@ucla.edu>:
On 3/17/2011 7:17 AM, Joachim Faulhaber wrote:
2011/3/17 Joachim Faulhaber<afojgo@googlemail.com>:
[...]
thank you again for implementing this has_operator extension. I've found some problems. In the ICL I have an operator +
[...]
template<class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const Type& operand);
and is seems that more overloads are checked valid as actually exist. Is this intentional?
BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT;
// This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value));
BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value));
// These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); }
An operator trait allows implicit conversions in the arguments. In fact, the current implementation strategy *must* allow implicit conversions in the arguments, i.e., I wouldn't know how to detect *exact* signatures.
Does this mean that, since is_convertible<T, T&> and is_convertible<T, T const&> has_operator_xxx comes with a built in type qualifier abstraction, which means that it does never make sense to use type qualifiers with has_operator_xxx<...>::value meta expressions? Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

On 3/17/2011 1:56 PM, Joachim Faulhaber wrote:
2011/3/17 Jeffrey Lee Hellrung, Jr.<jhellrung@ucla.edu>:
On 3/17/2011 7:17 AM, Joachim Faulhaber wrote:
2011/3/17 Joachim Faulhaber<afojgo@googlemail.com>:
[...]
thank you again for implementing this has_operator extension. I've found some problems. In the ICL I have an operator +
[...]
template<class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const Type& operand);
and is seems that more overloads are checked valid as actually exist. Is this intentional?
BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT;
// This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value));
BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value));
// These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); }
An operator trait allows implicit conversions in the arguments. In fact, the current implementation strategy *must* allow implicit conversions in the arguments, i.e., I wouldn't know how to detect *exact* signatures.
Does this mean that, since
is_convertible<T, T&> and
Not typically true, as rvalues aren't (supposed to be) implicitly convertible to references-to-non-const.
is_convertible<T, T const&>
True, but only half the story. We also have the conversions T & -> T const & T & -> T [if T is copy-constructible] T const & -> T [if T is copy-constructible]
has_operator_xxx comes with a built in type qualifier abstraction, which means that it does never make sense to use type qualifiers with has_operator_xxx<...>::value meta expressions?
Here is my understanding of what *should* be happening, although I'd have to take a closer look at the implementation and/or wait for Frederic to verify/refute this assertion. You do want to use type qualifiers in the arguments if you care about constness or copy constructibility. E.g., has_operator_xxx< some_type&
might be true while has_operator_xxx< some_type > and/or has_operator_xxx< some_type const & > could be false, depending on the signature of operator_xxx. E.g., std::map<...>::operator[].
Basically, you should invoke the has_operator_xxx metafunctions with argument types (including const and reference qualifiers) that match how you actually invoke the operator. Same deal as with boost::result_of. - Jeff

2011/3/17 Jeffrey Lee Hellrung, Jr. <jhellrung@ucla.edu>:
On 3/17/2011 1:56 PM, Joachim Faulhaber wrote:
2011/3/17 Jeffrey Lee Hellrung, Jr.<jhellrung@ucla.edu>:
On 3/17/2011 7:17 AM, Joachim Faulhaber wrote:
2011/3/17 Joachim Faulhaber<afojgo@googlemail.com>:
[...]
thank you again for implementing this has_operator extension. I've found some problems. In the ICL I have an operator +
[...]
template<class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const Type& operand);
and is seems that more overloads are checked valid as actually exist. Is this intentional?
BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT;
// This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value));
BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value));
// These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); }
An operator trait allows implicit conversions in the arguments. In fact, the current implementation strategy *must* allow implicit conversions in the arguments, i.e., I wouldn't know how to detect *exact* signatures.
Does this mean that, since
is_convertible<T, T&> and
Not typically true, as rvalues aren't (supposed to be) implicitly convertible to references-to-non-const.
is_convertible<T, T const&>
True, but only half the story. We also have the conversions
T & -> T const & T & -> T [if T is copy-constructible] T const & -> T [if T is copy-constructible]
has_operator_xxx comes with a built in type qualifier abstraction, which means that it does never make sense to use type qualifiers with has_operator_xxx<...>::value meta expressions?
Here is my understanding of what *should* be happening, although I'd have to take a closer look at the implementation and/or wait for Frederic to verify/refute this assertion.
You do want to use type qualifiers in the arguments if you care about constness or copy constructibility. E.g., has_operator_xxx< some_type& > might be true while has_operator_xxx< some_type > and/or has_operator_xxx< some_type const & > could be false, depending on the signature of operator_xxx. E.g., std::map<...>::operator[].
Basically, you should invoke the has_operator_xxx metafunctions with argument types (including const and reference qualifiers) that match how you actually invoke the operator. Same deal as with boost::result_of.
It seems like these rules should be put down in the documentation along with some good illustrating examples. Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

On 3/17/2011 3:19 PM, Joachim Faulhaber wrote:
2011/3/17 Jeffrey Lee Hellrung, Jr.<jhellrung@ucla.edu>: [...]
Here is my understanding of what *should* be happening, although I'd have to take a closer look at the implementation and/or wait for Frederic to verify/refute this assertion.
You do want to use type qualifiers in the arguments if you care about constness or copy constructibility. E.g., has_operator_xxx< some_type& > might be true while has_operator_xxx< some_type> and/or has_operator_xxx< some_type const& > could be false, depending on the signature of operator_xxx. E.g., std::map<...>::operator[].
Basically, you should invoke the has_operator_xxx metafunctions with argument types (including const and reference qualifiers) that match how you actually invoke the operator. Same deal as with boost::result_of.
It seems like these rules should be put down in the documentation along with some good illustrating examples.
Actually, I'm wrong, at least regarding the current implementation. It looks like a reference qualifier is assumed for the argument types, so only const (and volatile) qualifiers matter (indeed, the current implementation probably won't compile on C++03, due to "reference of reference errors"). And indeed, implicit in the documentation, all operator traits assume the arguments are lvalues. Is this the desired behavior? I guess I've been influenced by http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf in 3.4 "Function return types" [tr.func.ret], page 23, regarding result_of: "Given an rvalue f of type F and values t1, t2, ..., tN of types T1, T2, ..., TN, respectively, the type member is the result type of the expression f(t1, t2, ...,tN). The values ti are lvalues when the corresponding type Ti is a reference type, and rvalues otherwise." The Boost.ResultOf documentation references this document, but at the same time there is no explicit distinction between lvalues and rvalues. - Jeff

has_operator_xxx comes with a built in type qualifier abstraction, which means that it does never make sense to use type qualifiers with has_operator_xxx<...>::value meta expressions?
it still does. Another example: T operator+(T&); has_operator_unary_plus<const T&>::value is false. This also is false: has_operator_plus_equal<const int, int>::value So you should use the types you want to pass to the operator, with cv and reference/pointer qualifiers. Frédéric

Frédéric Bron wrote:
has_operator_xxx comes with a built in type qualifier abstraction, which means that it does never make sense to use type qualifiers with has_operator_xxx<...>::value meta expressions?
it still does.
Another example: T operator+(T&); has_operator_unary_plus::value is false.
This also is false: has_operator_plus_equal::value
So you should use the types you want to pass to the operator, with cv and reference/pointer qualifiers.
Hi, I suspect this need much more clarification than some examples in the documentation. Please could you try to specify the semantics in a formal way? Thanks, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/Review-Boost-Type-Traits-Extension-by-Fre... Sent from the Boost - Dev mailing list archive at Nabble.com.

I've found some problems. In the ICL I have an operator +
template <class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const Type& operand);
and is seems that more overloads are checked valid as actually exist. Is this intentional?
BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT;
// This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value));
BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value));
// These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); }
Your question here is the same as the following example: struct T { }; struct RET { }; RET f(T, const T&) { return RET(); } void g(RET) { } void h(const RET&) { } int main() { //Does this work? { T t1; const T &t2=t1; g(f(t1, t2)); } // -> yes { T t1; T &t2=t1; g(f(t1, t2)); } // -> yes { T t1; T t2; g(f(t1, t2)); } // -> yes { T t1; T t2; h(f(t1, t2)); } // -> yes return 0; } What it means it that has_operator_plus<LHS, RHS, RET> does not check for exact conformance of arguments LHS and RHS but checks if you can use LHS and RHS as arguments to the operator. And clearly you can use a lot of types when your operator is declared taking a const RHS&. Hope this helps. I think this policy is desirable otherwise you would have to test many options, especially with binary operators before being sure you can use the operator. Frédéric

2011/3/18 Frédéric Bron <frederic.bron@m4x.org>:
I've found some problems. In the ICL I have an operator +
template <class Type> inline typename enable_if <is_associative_element_container<Type>, Type>::type operator + (Type object, const Type& operand);
and is seems that more overloads are checked valid as actually exist. Is this intentional?
BOOST_AUTO_TEST_CASE(has_op_extension_qualifiers) { typedef int T; typedef interval_set<T> IntervalSetT; typedef IntervalSetT::interval_type IntervalT;
// This is supposed to succeed BOOST_CHECK((has_operator_plus<IntervalSetT, const IntervalSetT&, IntervalSetT>::value));
BOOST_CHECK((!is_convertible<const IntervalSetT&, IntervalSetT&>::value));
// These are supposed to fail, but they succeed BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT&, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT>::value)); BOOST_CHECK((has_operator_plus<IntervalSetT, IntervalSetT, IntervalSetT const&>::value)); }
Your question here is the same as the following example:
struct T { }; struct RET { };
RET f(T, const T&) { return RET(); } void g(RET) { } void h(const RET&) { }
int main() { //Does this work? { T t1; const T &t2=t1; g(f(t1, t2)); } // -> yes { T t1; T &t2=t1; g(f(t1, t2)); } // -> yes { T t1; T t2; g(f(t1, t2)); } // -> yes { T t1; T t2; h(f(t1, t2)); } // -> yes return 0; }
What it means it that has_operator_plus<LHS, RHS, RET> does not check for exact conformance of arguments LHS and RHS but checks if you can use LHS and RHS as arguments to the operator.
understood. Doesn't this mean, that the naming has_operator_xxx is imprecise and should be operator_xxx_applicable_to or operator_xxx_callable_on instead? Joachim -- Interval Container Library [Boost.Icl] http://www.joachim-faulhaber.de

On 3/18/2011 12:39 PM, Frédéric Bron wrote:
Doesn't this mean, that the naming has_operator_xxx is imprecise and should be operator_xxx_applicable_to or operator_xxx_callable_on instead?
That is the right meaning.
But the wrong name. IMO nobody is going to be comfortable with 'operator_xxx_callable_on' as opposed to 'has_operator_xxx'.
participants (12)
-
Edward Diener
-
Frédéric Bron
-
Jeffrey Lee Hellrung, Jr.
-
Joachim Faulhaber
-
Joel Falcou
-
Max Sobolev
-
Paul A. Bristow
-
Stewart, Robert
-
Thomas Heller
-
Thomas Klimpel
-
Vicente Botet
-
Тимофей Игнатьич