Fix LWG 2934 - optional<const T> doesn't compare with T

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@299105 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2017-03-30 20:06:52 +00:00
parent 5612bd42dc
commit 2b3c1c4d9b
14 changed files with 577 additions and 443 deletions

View File

@@ -921,14 +921,14 @@ private:
};
// Comparisons between optionals
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
operator==(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return false;
@@ -937,14 +937,14 @@ operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
return *__x == *__y;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
operator!=(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (static_cast<bool>(__x) != static_cast<bool>(__y))
return true;
@@ -953,14 +953,14 @@ operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
return *__x != *__y;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
operator<(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__y))
return false;
@@ -969,14 +969,14 @@ operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
return *__x < *__y;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
operator>(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__x))
return false;
@@ -985,14 +985,14 @@ operator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
return *__x > *__y;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
operator<=(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__x))
return true;
@@ -1001,14 +1001,14 @@ operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
return *__x <= *__y;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y)
operator>=(const optional<_Tp>& __x, const optional<_Up>& __y)
{
if (!static_cast<bool>(__y))
return true;
@@ -1115,146 +1115,146 @@ operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
}
// Comparisons with T
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator==(const optional<_Tp>& __x, const _Tp& __v)
operator==(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x == __v : false;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator==(const _Tp& __v, const optional<_Tp>& __x)
operator==(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v == *__x : false;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator!=(const optional<_Tp>& __x, const _Tp& __v)
operator!=(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x != __v : true;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator!=(const _Tp& __v, const optional<_Tp>& __x)
operator!=(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v != *__x : true;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<(const optional<_Tp>& __x, const _Tp& __v)
operator<(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x < __v : true;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<(const _Tp& __v, const optional<_Tp>& __x)
operator<(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v < *__x : false;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<=(const optional<_Tp>& __x, const _Tp& __v)
operator<=(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x <= __v : true;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator<=(const _Tp& __v, const optional<_Tp>& __x)
operator<=(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v <= *__x : false;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>(const optional<_Tp>& __x, const _Tp& __v)
operator>(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x > __v : false;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>(const _Tp& __v, const optional<_Tp>& __x)
operator>(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v > *__x : true;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>=(const optional<_Tp>& __x, const _Tp& __v)
operator>=(const optional<_Tp>& __x, const _Up& __v)
{
return static_cast<bool>(__x) ? *__x >= __v : false;
}
template <class _Tp>
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY constexpr
enable_if_t<
is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
_VSTD::declval<const _Tp&>()), bool>,
_VSTD::declval<const _Up&>()), bool>,
bool
>
operator>=(const _Tp& __v, const optional<_Tp>& __x)
operator>=(const _Tp& __v, const optional<_Up>& __x)
{
return static_cast<bool>(__x) ? __v >= *__x : true;
}

View File

@@ -17,18 +17,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator == ( const X &lhs, const X &rhs )
{ return lhs.i_ == rhs.i_ ; }
constexpr bool operator==(const X& lhs, const X& rhs) {
return lhs.i_ == rhs.i_;
}
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -50,4 +49,16 @@ int main()
static_assert((T(2) == o3), "");
static_assert((val == o3), "");
}
{
using O = optional<int>;
constexpr O o1(42);
static_assert(o1 == 42l, "");
static_assert(!(101l == o1), "");
}
{
using O = optional<const int>;
constexpr O o1(42);
static_assert(o1 == 42, "");
static_assert(!(101 == o1), "");
}
}

View File

@@ -17,18 +17,15 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator > ( const X &lhs, const X &rhs )
{ return lhs.i_ > rhs.i_ ; }
constexpr bool operator>(const X& lhs, const X& rhs) { return lhs.i_ > rhs.i_; }
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -52,4 +49,16 @@ int main()
static_assert(!(val > o3), ""); // equal
static_assert((T(3) > o3), "");
}
{
using O = optional<int>;
constexpr O o1(42);
static_assert(o1 > 11l, "");
static_assert(!(42l > o1), "");
}
{
using O = optional<const int>;
constexpr O o1(42);
static_assert(o1 > 11, "");
static_assert(!(42 > o1), "");
}
}

View File

@@ -17,18 +17,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator >= ( const X &lhs, const X &rhs )
{ return lhs.i_ >= rhs.i_ ; }
constexpr bool operator>=(const X& lhs, const X& rhs) {
return lhs.i_ >= rhs.i_;
}
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -52,4 +51,16 @@ int main()
static_assert((val >= o3), ""); // equal
static_assert((T(3) >= o3), "");
}
{
using O = optional<int>;
constexpr O o1(42);
static_assert(o1 >= 42l, "");
static_assert(!(11l >= o1), "");
}
{
using O = optional<const int>;
constexpr O o1(42);
static_assert(o1 >= 42, "");
static_assert(!(11 >= o1), "");
}
}

View File

@@ -17,18 +17,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator <= ( const X &lhs, const X &rhs )
{ return lhs.i_ <= rhs.i_ ; }
constexpr bool operator<=(const X& lhs, const X& rhs) {
return lhs.i_ <= rhs.i_;
}
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -52,4 +51,16 @@ int main()
static_assert((val <= o3), ""); // equal
static_assert(!(T(3) <= o3), "");
}
{
using O = optional<int>;
constexpr O o1(42);
static_assert(o1 <= 42l, "");
static_assert(!(101l <= o1), "");
}
{
using O = optional<const int>;
constexpr O o1(42);
static_assert(o1 <= 42, "");
static_assert(!(101 <= o1), "");
}
}

View File

@@ -17,18 +17,15 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator < ( const X &lhs, const X &rhs )
{ return lhs.i_ < rhs.i_ ; }
constexpr bool operator<(const X& lhs, const X& rhs) { return lhs.i_ < rhs.i_; }
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -52,4 +49,16 @@ int main()
static_assert(!(val < o3), ""); // equal
static_assert(!(T(3) < o3), "");
}
{
using O = optional<int>;
constexpr O o1(42);
static_assert(o1 < 101l, "");
static_assert(!(42l < o1), "");
}
{
using O = optional<const int>;
constexpr O o1(42);
static_assert(o1 < 101, "");
static_assert(!(42 < o1), "");
}
}

View File

@@ -17,18 +17,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator != ( const X &lhs, const X &rhs )
{ return lhs.i_ != rhs.i_ ; }
constexpr bool operator!=(const X& lhs, const X& rhs) {
return lhs.i_ != rhs.i_;
}
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -50,4 +49,16 @@ int main()
static_assert(!(T(2) != o3), "");
static_assert(!(val != o3), "");
}
{
using O = optional<int>;
constexpr O o1(42);
static_assert(o1 != 101l, "");
static_assert(!(42l != o1), "");
}
{
using O = optional<const int>;
constexpr O o1(42);
static_assert(o1 != 101, "");
static_assert(!(42 != o1), "");
}
}

View File

@@ -18,18 +18,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator == ( const X &lhs, const X &rhs )
{ return lhs.i_ == rhs.i_ ; }
constexpr bool operator==(const X& lhs, const X& rhs) {
return lhs.i_ == rhs.i_;
}
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -69,6 +68,19 @@ int main()
static_assert(o5 == o3, "");
static_assert(!(o5 == o4), "");
static_assert(o5 == o5, "");
}
{
using O1 = optional<int>;
using O2 = optional<long>;
constexpr O1 o1(42);
static_assert(o1 == O2(42), "");
static_assert(!(O2(101) == o1), "");
}
{
using O1 = optional<int>;
using O2 = optional<const int>;
constexpr O1 o1(42);
static_assert(o1 == O2(42), "");
static_assert(!(O2(101) == o1), "");
}
}

View File

@@ -16,18 +16,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator >= ( const X &lhs, const X &rhs )
{ return lhs.i_ >= rhs.i_ ; }
constexpr bool operator>=(const X& lhs, const X& rhs) {
return lhs.i_ >= rhs.i_;
}
int main()
{
int main() {
{
typedef optional<X> O;
@@ -67,4 +66,18 @@ int main()
static_assert(!(o5 >= o4), "");
static_assert((o5 >= o5), "");
}
{
using O1 = optional<int>;
using O2 = optional<long>;
constexpr O1 o1(42);
static_assert(o1 >= O2(42), "");
static_assert(!(O2(11) >= o1), "");
}
{
using O1 = optional<int>;
using O2 = optional<const int>;
constexpr O1 o1(42);
static_assert(o1 >= O2(42), "");
static_assert(!(O2(1) >= o1), "");
}
}

View File

@@ -16,18 +16,15 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator > ( const X &lhs, const X &rhs )
{ return lhs.i_ > rhs.i_ ; }
constexpr bool operator>(const X& lhs, const X& rhs) { return lhs.i_ > rhs.i_; }
int main()
{
int main() {
{
typedef optional<X> O;
@@ -67,4 +64,18 @@ int main()
static_assert(!(o5 > o4), "");
static_assert(!(o5 > o5), "");
}
{
using O1 = optional<int>;
using O2 = optional<long>;
constexpr O1 o1(42);
static_assert(o1 > O2(1), "");
static_assert(!(O2(42) > o1), "");
}
{
using O1 = optional<int>;
using O2 = optional<const int>;
constexpr O1 o1(42);
static_assert(o1 > O2(1), "");
static_assert(!(O2(42) > o1), "");
}
}

View File

@@ -16,18 +16,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator <= ( const X &lhs, const X &rhs )
{ return lhs.i_ <= rhs.i_ ; }
constexpr bool operator<=(const X& lhs, const X& rhs) {
return lhs.i_ <= rhs.i_;
}
int main()
{
int main() {
{
typedef optional<X> O;
@@ -67,4 +66,18 @@ int main()
static_assert((o5 <= o4), "");
static_assert((o5 <= o5), "");
}
{
using O1 = optional<int>;
using O2 = optional<long>;
constexpr O1 o1(42);
static_assert(o1 <= O2(42), "");
static_assert(!(O2(101) <= o1), "");
}
{
using O1 = optional<int>;
using O2 = optional<const int>;
constexpr O1 o1(42);
static_assert(o1 <= O2(42), "");
static_assert(!(O2(101) <= o1), "");
}
}

View File

@@ -16,18 +16,15 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator < ( const X &lhs, const X &rhs )
{ return lhs.i_ < rhs.i_ ; }
constexpr bool operator<(const X& lhs, const X& rhs) { return lhs.i_ < rhs.i_; }
int main()
{
int main() {
{
typedef optional<X> O;
@@ -67,4 +64,18 @@ int main()
static_assert((o5 < o4), "");
static_assert(!(o5 < o5), "");
}
{
using O1 = optional<int>;
using O2 = optional<long>;
constexpr O1 o1(42);
static_assert(o1 < O2(101), "");
static_assert(!(O2(101) < o1), "");
}
{
using O1 = optional<int>;
using O2 = optional<const int>;
constexpr O1 o1(42);
static_assert(o1 < O2(101), "");
static_assert(!(O2(101) < o1), "");
}
}

View File

@@ -18,18 +18,17 @@
using std::optional;
struct X
{
struct X {
int i_;
constexpr X(int i) : i_(i) {}
};
constexpr bool operator != ( const X &lhs, const X &rhs )
{ return lhs.i_ != rhs.i_ ; }
constexpr bool operator!=(const X& lhs, const X& rhs) {
return lhs.i_ != rhs.i_;
}
int main()
{
int main() {
{
typedef X T;
typedef optional<T> O;
@@ -69,6 +68,19 @@ int main()
static_assert(!(o5 != o3), "");
static_assert((o5 != o4), "");
static_assert(!(o5 != o5), "");
}
{
using O1 = optional<int>;
using O2 = optional<long>;
constexpr O1 o1(42);
static_assert(o1 != O2(101), "");
static_assert(!(O2(42) != o1), "");
}
{
using O1 = optional<int>;
using O2 = optional<const int>;
constexpr O1 o1(42);
static_assert(o1 != O2(101), "");
static_assert(!(O2(42) != o1), "");
}
}

View File

@@ -482,7 +482,7 @@
<tr><td><a href="http://wg21.link/LWG2908">2908</a></td><td>The less-than operator for shared pointers could do more</td><td>Kona</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2911">2911</a></td><td>An is_aggregate type trait is needed</td><td>Kona</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2921">2921</a></td><td>packaged_task and type-erased allocators</td><td>Kona</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2934">2934</a></td><td>optional&lt;const T&gt; doesn't compare with T</td><td>Kona</td><td></td></tr>
<tr><td><a href="http://wg21.link/LWG2934">2934</a></td><td>optional&lt;const T&gt; doesn't compare with T</td><td>Kona</td><td>Complete</td></tr>
<!--
<tr><td><a href="http://wg21.link/LWG1214">1214</a></td><td>Insufficient/inconsistent key immutability requirements for associative containers</td><td>Urbana</td><td></td></tr>
-->