[boost] [type_traits] has_equal_to< std::vector<T> > always true_

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
36 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[boost] [type_traits] has_equal_to< std::vector<T> > always true_

lcaminiti
Hello all,

has_equal_to< std::vector<T> > always returns true_ because == is defined for std::vector<T> even when it is not defined for T. However, then an attempt to compare for equality std::vector<T> will generate a compiler error in this case because there is no == for T.

For example:

#include <boost/type_traits/has_equal_to.hpp>
#include <vector>
#include <iostream>

struct myvalue {};

//bool operator== ( myvalue const& l, myvalue const& r ) { return false; } // (1)

int main ( )
{
    typedef std::vector<myvalue> myvector;
    std::cout << boost::has_equal_to<myvector>::value << std::endl; // always returns true
    myvector v(1), w(1);
    std::cout << (v == w) << std::endl; // compiler error because (1) is not defined
    return 0;
}

Shall has_equal_to< std::vector<T> > be smarter and return false_ if T does not have == ? (If not, this case should at least be documented.)

P.S. Are the strange HTML tags for < and > gone?

Thanks a lot.
--Lorenzo
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Jeffrey Lee Hellrung, Jr.-2
On Thu, Oct 20, 2011 at 7:55 AM, lcaminiti <[hidden email]> wrote:

> Hello all,
>
> has_equal_to< std::vector<T> > always returns true_ because == is defined for std::vector<T> even when it is not defined for T. However, then an attempt to compare for equality std::vector<T> will generate a compiler error in this case because there is no == for T.
>
> For example:
>
> #include <boost/type_traits/has_equal_to.hpp>
> #include <vector>
> #include <iostream>
>
> struct myvalue {};
>
> //bool operator== ( myvalue const& l, myvalue const& r ) { return false; } // (1)
>
> int main ( )
> {
>     typedef std::vector<myvalue> myvector;
>     std::cout << boost::has_equal_to<myvector>::value << std::endl; // always returns true
>     myvector v(1), w(1);
>     std::cout << (v == w) << std::endl; // compiler error because (1) is not defined
>     return 0;
> }
>
> Shall has_equal_to< std::vector<T> > be smarter and return false_ if T does not have == ? (If not, this case should at least be documented.)
>
>
I'd venture to say this is a deficiency in std::vector's implementation of
operator==, which ideally should SFINAE-out bindings of T which do not have
an operator==.  You get the same sort of problem if you have a class with an
unbounded conversion constructor template:

struct X
{
    template< class T >
    X(T x)
    { /*...*/ }
};

Here, I believe, boost::is_convertible< Y, X > will evaluate to true, and
some bindings of Y to T may result in a compiler error (depending on what's
in /*...*/).  I *seem* to remember this was a problem with boost::variant,
for example, but even if it wasn't, you can imagine how it could be (the
template parameter in the constructor should only be bindable to one of the
value_types of the variant).

In my opinion, the upshot is that std::vector's operator== is almost
certainly not a special case, so I don't know know if it's worth
specializing has_equal_to on it or not.  Maybe, if it's consistently done
for all problematic std-defined operators?

P.S. Are the strange HTML tags for < and > gone?
>
>
Yes, but the above quoted message only appeared when I clicked on the link:

http://boost.2283326.n4.nabble.com/boost-type-traits-has-equal-to-lt-std-vector-lt-T-gt-gt-always-true-td3922160.html

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Vicente Botet
Le 20/10/11 17:09, Jeffrey Lee Hellrung, Jr. a écrit :
> On Thu, Oct 20, 2011 at 7:55 AM, lcaminiti<[hidden email]>  wrote:
>
>> Hello all,
>>
>> has_equal_to<  std::vector<T>  >  always returns true_ because == is defined for std::vector<T>  even when it is not defined for T. However, then an attempt to compare for equality std::vector<T>  will generate a compiler error in this case because there is no == for T.
>>
<snip>
>>
>> Shall has_equal_to<  std::vector<T>  >  be smarter and return false_ if T does not have == ? (If not, this case should at least be documented.)
>>
>>
> I'd venture to say this is a deficiency in std::vector's implementation of
> operator==, which ideally should SFINAE-out bindings of T which do not have
> an operator==.
<snip>
>
> In my opinion, the upshot is that std::vector's operator== is almost
> certainly not a special case, so I don't know know if it's worth
> specializing has_equal_to on it or not.  Maybe, if it's consistently done
> for all problematic std-defined operators?
>
Hi,

I found the same kind of issues while implementing
is_constructible/is_assignable/is_convertible for Boost.Conversion. The
option I taken was to specialize these traits for the c++
implementations that were not using SFINAE. This force of course the
user to include the specific file containing the specialization.

BTW Ion, it seems that your implementation on Boost.Container is not
using SFINAE neither. Please, could you add them to conform to the C++11
specification?

Best,
Vicente


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

lcaminiti
Vicente Botet wrote
Le 20/10/11 17:09, Jeffrey Lee Hellrung, Jr. a écrit :
> On Thu, Oct 20, 2011 at 7:55 AM, lcaminiti<[hidden email]>  wrote:
>
>> Hello all,
>>
>> has_equal_to<  std::vector<T>  >  always returns true_ because == is defined for std::vector<T>  even when it is not defined for T. However, then an attempt to compare for equality std::vector<T>  will generate a compiler error in this case because there is no == for T.
>>
<snip>
>>
>> Shall has_equal_to<  std::vector<T>  >  be smarter and return false_ if T does not have == ? (If not, this case should at least be documented.)
>>
>>
> I'd venture to say this is a deficiency in std::vector's implementation of
> operator==, which ideally should SFINAE-out bindings of T which do not have
> an operator==.
<snip>
>
> In my opinion, the upshot is that std::vector's operator== is almost
> certainly not a special case, so I don't know know if it's worth
> specializing has_equal_to on it or not.  Maybe, if it's consistently done
> for all problematic std-defined operators?
>
Hi,

I found the same kind of issues while implementing
is_constructible/is_assignable/is_convertible for Boost.Conversion. The
option I taken was to specialize these traits for the c++
implementations that were not using SFINAE. This force of course the
user to include the specific file containing the specialization.
Would the Boost.TypeTraits authors consider adding the specializations* to workaround STL not using SFINAE? If not, can these cases be documented?

(*) In this case it'd be nice to name the headers containing the extra specialization consistently with other Boost libraries like Boost.Conversion-- Vicente, how did you name the headers containing the specialization for the STL types?

Thanks.
--Lorenzo
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Vicente Botet
Le 21/10/11 17:38, lcaminiti a écrit :

> Vicente Botet wrote:
>> Hi,
>>
>> I found the same kind of issues while implementing
>> is_constructible/is_assignable/is_convertible for Boost.Conversion. The
>> option I taken was to specialize these traits for the c++
>> implementations that were not using SFINAE. This force of course the
>> user to include the specific file containing the specialization.
>>
> Would the Boost.TypeTraits authors consider adding the specializations* to
> workaround STL not using SFINAE? If not, can these cases be documented?
>
> (*) In this case it'd be nice to name the headers containing the extra
> specialization consistently with other Boost libraries like
> Boost.Conversion-- Vicente, how did you name the headers containing the
> specialization for the STL types?
>
I added all of them in a std directory with the same name as in the
standard. For example

boost/conversion/std/utility.hpp included some specializations for
std::pair,
boost/conversion/std/vector.hpp included some specializations for
std::vector,
...

In this way the user just needs to replace

#include <utility>

by

#include <boost/conversion/std/utility.hpp>

If several libraries use the same convention, it will be quite easy to
provide some files that add some specificities to the standard files in
for example the directory std

boost/std/utility.hpp could include

   #include <boost/type_traits/std/utility.hpp>
   #include <boost/serialization/std/utility.hpp>
   #include <boost/XXXX/std/utility.hpp>
   ....


Best,
Vicente







_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Frédéric Bron
In reply to this post by lcaminiti
>>>> has_equal_to<  std::vector<T>  >  always returns true
> Would the Boost.TypeTraits authors consider adding the specializations* to
> workaround STL not using SFINAE? If not, can these cases be documented?

Hi,

Thanks for highlighting this major issue. I understand that there is
nothing to do apart from specializing the traits for those particular
std classes. This would however not work with user classes. As the
beta is due on Monday, I believe it is too short to submit a working
and tested patch. Maybe once the beta is out, you can start to work on
a proposed contribution?
Meanwhile, as suggested I will add a warning in the doc.

> boost/conversion/std/vector.hpp included some specializations for
> std::vector,

This seems a reasonable naming convention.

Regards,
Frédéric

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Dave Abrahams

on Fri Oct 21 2011, Frédéric Bron <frederic.bron-AT-m4x.org> wrote:

>>>>> has_equal_to<  std::vector<T>  >  always returns true
>> Would the Boost.TypeTraits authors consider adding the specializations* to
>> workaround STL not using SFINAE? If not, can these cases be documented?
>
> Hi,
>
> Thanks for highlighting this major issue. I understand that there is
> nothing to do apart from specializing the traits for those particular
> std classes. This would however not work with user classes. As the
> beta is due on Monday, I believe it is too short to submit a working
> and tested patch. Maybe once the beta is out, you can start to work on
> a proposed contribution?

I'm not sure, but it's *conceivable* that with C++11 extended SFINAE it
might be possible to produce a has_equal_to that fails if the operator
can't be instantiated.  Somebody else around here surely knows better
than I do.

--
Dave Abrahams
BoostPro Computing
http://www.boostpro.com


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Frédéric Bron
In reply to this post by Frédéric Bron
> Thanks for highlighting this major issue. I understand that there is
> nothing to do apart from specializing the traits for those particular
> std classes. This would however not work with user classes. As the
> beta is due on Monday, I believe it is too short to submit a working
> and tested patch. Maybe once the beta is out, you can start to work on
> a proposed contribution?
> Meanwhile, as suggested I will add a warning in the doc.

I have committed to trunk (r75084) and branches/release (r75085) a
documentation patch that explains the issue with an example.
Regards,
Frédéric

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Vicente Botet
In reply to this post by Dave Abrahams
Le 22/10/11 01:13, Dave Abrahams a écrit :

> on Fri Oct 21 2011, Frédéric Bron<frederic.bron-AT-m4x.org>  wrote:
>
>>>>>> has_equal_to<    std::vector<T>    >    always returns true
>>> Would the Boost.TypeTraits authors consider adding the specializations* to
>>> workaround STL not using SFINAE? If not, can these cases be documented?
>> Hi,
>>
>> Thanks for highlighting this major issue. I understand that there is
>> nothing to do apart from specializing the traits for those particular
>> std classes. This would however not work with user classes. As the
>> beta is due on Monday, I believe it is too short to submit a working
>> and tested patch. Maybe once the beta is out, you can start to work on
>> a proposed contribution?
> I'm not sure, but it's *conceivable* that with C++11 extended SFINAE it
> might be possible to produce a has_equal_to that fails if the operator
> can't be instantiated.  Somebody else around here surely knows better
> than I do.
>
I think so. The problem appears with compilers that don't supports C++11
extended SFINAE and those standard library doesn't protect the operator
instantiation.

Vicente

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > alwaystrue_

John Maddock-3
In reply to this post by Frédéric Bron
>Thanks for highlighting this major issue. I understand that there is
>nothing to do apart from specializing the traits for those particular
>std classes. This would however not work with user classes. As the
>beta is due on Monday, I believe it is too short to submit a working
>and tested patch. Maybe once the beta is out, you can start to work on
>a proposed contribution?
>Meanwhile, as suggested I will add a warning in the doc.

It's a tricky one, because strictly speaking vector<T> always does have an
equality operator - it's just that depending upon T it may not compile :-(

There's no general solution to this, because there's no way in the language
to test whether something does or does not compile - we can only test
whether it's declared or not.

John.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > alwaystrue_

Vicente Botet
Le 22/10/11 10:25, John Maddock a écrit :

>> Thanks for highlighting this major issue. I understand that there is
>> nothing to do apart from specializing the traits for those particular
>> std classes. This would however not work with user classes. As the
>> beta is due on Monday, I believe it is too short to submit a working
>> and tested patch. Maybe once the beta is out, you can start to work on
>> a proposed contribution?
>> Meanwhile, as suggested I will add a warning in the doc.
>
> It's a tricky one, because strictly speaking vector<T> always does
> have an equality operator - it's just that depending upon T it may not
> compile :-(
>
> There's no general solution to this, because there's no way in the
> language to test whether something does or does not compile - we can
> only test whether it's declared or not.
>
Hi,

I'm not sure  I understand the standard correctly. The standard says
container requirements "Requires: T is EqualityComparable".

Does this means that the operator== must not participate in overload
resolution when the requirements are not meet, or that the compilation
will fail?
IMO, it is the first. In other parts of the standard the wording is more
explicit. For example in the chrono part, every function that has some
constraints in the template types, state something like:

"Remarks: This operator shall not participate in overload resolution
unless Rep2 is implicitly convertible to CR(Rep1, Rep2)."


The same kind of wording is found for std::pair:

"
template<class U, class V> pair(const pair<U, V>& p);
Requires: is_constructible<first_type, const U&>::value is true and
is_constructible<second_- type, const V&>::value is true.
Effects: Initializes members from the corresponding members of the
argument.
Remark: This constructor shall not participate in overload resolution
unless const U& is implicitly convertible to first_type and const V& is
implicitly convertible to second_type.
"

I don't know if the standard is not enough precise respect to the
operator== for container, but this merits clarification anyway.

Best,
Vicente

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

lcaminiti
In reply to this post by Frédéric Bron
2011/10/21 Frédéric Bron <[hidden email]>:

>>>>> has_equal_to<  std::vector<T>  >  always returns true
>> Would the Boost.TypeTraits authors consider adding the specializations* to
>> workaround STL not using SFINAE? If not, can these cases be documented?
>
> Hi,
>
> Thanks for highlighting this major issue. I understand that there is
> nothing to do apart from specializing the traits for those particular
> std classes. This would however not work with user classes. As the
> beta is due on Monday, I believe it is too short to submit a working
> and tested patch. Maybe once the beta is out, you can start to work on
> a proposed contribution?
> Meanwhile, as suggested I will add a warning in the doc.

Makes sense.

>> boost/conversion/std/vector.hpp included some specializations for
>> std::vector,
>
> This seems a reasonable naming convention.

I agree (in fact, if I ever decide it's worth to provide a contracted
version of the STL, it'll be in boost/contract/std/vector.hpp, etc).

--Lorenzo

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > alwaystrue_

Ion Gaztañaga
In reply to this post by Vicente Botet
El 22/10/2011 12:18, Vicente J. Botet Escriba escribió:
> I'm not sure I understand the standard correctly. The standard says
> container requirements "Requires: T is EqualityComparable".
>
> Does this means that the operator== must not participate in overload
> resolution when the requirements are not meet, or that the compilation
> will fail?
> IMO, it is the first. In other parts of the standard the wording is more
> explicit. For example in the chrono part, every function that has some
> constraints in the template types, state something like:

I don't know if the first option is the correct, and I don't know if
is_default_constructible<std::vector<T>> should be false because T might
not be MoveConstructible.

If it is not guaranteed by the standard, I don't think we should offer
it. Making non-templated functions templated to use SFINAE could not
provoke some unwanted ambiguities?

Ion

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > alwaystrue_

Howard Hinnant-3
In reply to this post by Vicente Botet
On Oct 22, 2011, at 6:18 AM, Vicente J. Botet Escriba wrote:

> I'm not sure  I understand the standard correctly. The standard says container requirements "Requires: T is EqualityComparable".
>
> Does this means that the operator== must not participate in overload resolution when the requirements are not meet, or that the compilation will fail?
> IMO, it is the first. In other parts of the standard the wording is more explicit. For example in the chrono part, every function that has some constraints in the template types, state something like:
>
> "Remarks: This operator shall not participate in overload resolution unless Rep2 is implicitly convertible to CR(Rep1, Rep2)."

The LWG did not intend that template functions be SFINAE'd unless it has a remark about not participating in overload resolution.  And such treatment was reserved for cases that required such treatment to avoid ambiguities in overload resolution, templated constructors so that the std::traits would behave correctly (as has been noted in this thread), or (in the case of chrono) to control conversions to desired subsets (e.g. exactly convertible).

Newer parts of the standard were more likely to be treated in this way than older parts, with a notable exception being the "do the right thing clause" for the  containers:  [sequence.reqmts]/p14-15.

We did not add a "SFINAE" requirement to operator== for vector because we did not have a has_equal_to trait.  Such a feature certainly seems plausible for a future standard, though it is always difficult to predict what will and won't pass through committee.

Howard


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > alwaystrue_

Howard Hinnant-3
In reply to this post by Ion Gaztañaga
On Oct 22, 2011, at 1:53 PM, Ion Gaztañaga wrote:

> I don't know if is_default_constructible<std::vector<T>> should be false because T might not be MoveConstructible.

std::vector<T> is always default constructible because this constructor places no requirements on T.

Howard


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > alwaystrue_

Ion Gaztañaga
El 22/10/2011 22:32, Howard Hinnant escribió:
> On Oct 22, 2011, at 1:53 PM, Ion Gaztañaga wrote:
>
>> I don't know if is_default_constructible<std::vector<T>>  should be false because T might not be MoveConstructible.
>
> std::vector<T>  is always default constructible because this constructor places no requirements on T.

thanks Howard, I missed that now vector can have just EmplaceInsertable
or just DefaultConstructible objects.

best,

Ion

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

lcaminiti
In reply to this post by Frédéric Bron
On Fri, Oct 21, 2011 at 5:02 PM, Frédéric Bron <[hidden email]> wrote:

>>>>> has_equal_to<  std::vector<T>  >  always returns true
>> Would the Boost.TypeTraits authors consider adding the specializations* to
>> workaround STL not using SFINAE? If not, can these cases be documented?
>
> Hi,
>
> Thanks for highlighting this major issue. I understand that there is
> nothing to do apart from specializing the traits for those particular
> std classes. This would however not work with user classes. As the
> beta is due on Monday, I believe it is too short to submit a working
> and tested patch. Maybe once the beta is out, you can start to work on
> a proposed contribution?
> Meanwhile, as suggested I will add a warning in the doc.
>
>> boost/conversion/std/vector.hpp included some specializations for
>> std::vector,
>
> This seems a reasonable naming convention.

Were these traits specialized for the STL in any of the latest Boost releases?

Thanks.
--Lorenzo

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Frédéric Bron
> Were these traits specialized for the STL in any of the latest Boost releases?

don't think so.
Frédéric

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

lcaminiti
Frédéric Bron wrote
> Were these traits specialized for the STL in any of the latest Boost releases?

don't think so.
Do I have permission to add the specializations for STL containers to trunk and then the to release 1.50?

1) I'd add something like this for each STL container that defines an operator==:

    template< typename T, class Alloc = std::allocator<T> >
    struct has_equal_to< std::vector<T, Alloc> > : has_equal_to<T> {};

2) I'd add similar specializations for all traits that apply !=, <=, etc.

3) I'd add the specializations in the trait header type_traits/has_equal_to.hpp, etc and not into special headers type_traits/std/vector.hpp, .etc (because when I use has_equal_to on std::vector I'd always expect it to work according to the specialized version as a user and achieving expected behavior should require no extra user step like including type_traits/std/vector.hpp).

I'm happy to change the code, check the regression tests, and I don't think any documentation needs to be changed (because the specializations just make the traits work as the user expects them to work).

What do you think?

Thanks.
--Lorenzo
Reply | Threaded
Open this post in threaded view
|

Re: [type_traits] has_equal_to< std::vector<T> > always true_

Vicente Botet
Le 25/04/12 15:02, lcaminiti a écrit :

> Frédéric Bron wrote
>>> Were these traits specialized for the STL in any of the latest Boost
>>> releases?
>> don't think so.
>>
> Do I have permission to add the specializations for STL containers to trunk
> and then the to release 1.50?
>
> 1) I'd add something like this for each STL container that defines an
> operator==:
>
>      template<  typename T, class Alloc = std::allocator<T>  >
>      struct has_equal_to<  std::vector<T, Alloc>  >  : has_equal_to<T>  {};
>
> 2) I'd add similar specializations for all traits that apply !=,<=, etc.
>
> 3) I'd add the specializations in the trait header
> type_traits/has_equal_to.hpp, etc and not into special headers
> type_traits/std/vector.hpp, .etc (because when I use has_equal_to on
> std::vector I'd always expect it to work according to the specialized
> version as a user and achieving expected behavior should require no extra
> user step like including type_traits/std/vector.hpp).
>
> I'm happy to change the code, check the regression tests, and I don't think
> any documentation needs to be changed (because the specializations just make
> the traits work as the user expects them to work).
>
> What do you think?


Why do you need to specialize this trait for STL containers? Do you mean
that has_equal_to doesn't work for them? if no why?

Sorry if this is something obvious.

Best,
Vicente

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
12