mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-24 20:29:39 +08:00
Fix PR30260 - optional<const T> not working.
This patch fixes PR30260 by using a (void*) cast on the placement argument to placement new to casts away the const. See also http://llvm.org/PR30260. As a drive by change this patch also changes the header guard for <experimental/optional> to _LIBCPP_EXPERIMENTAL_OPTIONAL from _LIBCPP_OPTIONAL. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@280775 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -8,8 +8,8 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef _LIBCPP_OPTIONAL
|
#ifndef _LIBCPP_EXPERIMENTAL_OPTIONAL
|
||||||
#define _LIBCPP_OPTIONAL
|
#define _LIBCPP_EXPERIMENTAL_OPTIONAL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
optional synopsis
|
optional synopsis
|
||||||
@@ -211,7 +211,7 @@ protected:
|
|||||||
: __engaged_(__x.__engaged_)
|
: __engaged_(__x.__engaged_)
|
||||||
{
|
{
|
||||||
if (__engaged_)
|
if (__engaged_)
|
||||||
::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
|
::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
@@ -220,7 +220,7 @@ protected:
|
|||||||
: __engaged_(__x.__engaged_)
|
: __engaged_(__x.__engaged_)
|
||||||
{
|
{
|
||||||
if (__engaged_)
|
if (__engaged_)
|
||||||
::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
|
::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
@@ -262,7 +262,7 @@ protected:
|
|||||||
: __engaged_(__x.__engaged_)
|
: __engaged_(__x.__engaged_)
|
||||||
{
|
{
|
||||||
if (__engaged_)
|
if (__engaged_)
|
||||||
::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
|
::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_);
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
@@ -271,7 +271,7 @@ protected:
|
|||||||
: __engaged_(__x.__engaged_)
|
: __engaged_(__x.__engaged_)
|
||||||
{
|
{
|
||||||
if (__engaged_)
|
if (__engaged_)
|
||||||
::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
|
::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
|
||||||
}
|
}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
@@ -368,7 +368,7 @@ public:
|
|||||||
if (this->__engaged_)
|
if (this->__engaged_)
|
||||||
this->__val_.~value_type();
|
this->__val_.~value_type();
|
||||||
else
|
else
|
||||||
::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
|
::new((void*)_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
|
||||||
this->__engaged_ = __opt.__engaged_;
|
this->__engaged_ = __opt.__engaged_;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -390,7 +390,8 @@ public:
|
|||||||
if (this->__engaged_)
|
if (this->__engaged_)
|
||||||
this->__val_.~value_type();
|
this->__val_.~value_type();
|
||||||
else
|
else
|
||||||
::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
|
::new((void*)_VSTD::addressof(this->__val_))
|
||||||
|
value_type(_VSTD::move(__opt.__val_));
|
||||||
this->__engaged_ = __opt.__engaged_;
|
this->__engaged_ = __opt.__engaged_;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -412,7 +413,7 @@ public:
|
|||||||
this->__val_ = _VSTD::forward<_Up>(__v);
|
this->__val_ = _VSTD::forward<_Up>(__v);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
|
::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
|
||||||
this->__engaged_ = true;
|
this->__engaged_ = true;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -429,7 +430,8 @@ public:
|
|||||||
emplace(_Args&&... __args)
|
emplace(_Args&&... __args)
|
||||||
{
|
{
|
||||||
*this = nullopt;
|
*this = nullopt;
|
||||||
::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
|
::new((void*)_VSTD::addressof(this->__val_))
|
||||||
|
value_type(_VSTD::forward<_Args>(__args)...);
|
||||||
this->__engaged_ = true;
|
this->__engaged_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +446,8 @@ public:
|
|||||||
emplace(initializer_list<_Up> __il, _Args&&... __args)
|
emplace(initializer_list<_Up> __il, _Args&&... __args)
|
||||||
{
|
{
|
||||||
*this = nullopt;
|
*this = nullopt;
|
||||||
::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
|
::new((void*)_VSTD::addressof(this->__val_))
|
||||||
|
value_type(__il, _VSTD::forward<_Args>(__args)...);
|
||||||
this->__engaged_ = true;
|
this->__engaged_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,12 +467,14 @@ public:
|
|||||||
{
|
{
|
||||||
if (this->__engaged_)
|
if (this->__engaged_)
|
||||||
{
|
{
|
||||||
::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
|
::new((void*)_VSTD::addressof(__opt.__val_))
|
||||||
|
value_type(_VSTD::move(this->__val_));
|
||||||
this->__val_.~value_type();
|
this->__val_.~value_type();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
|
::new((void*)_VSTD::addressof(this->__val_))
|
||||||
|
value_type(_VSTD::move(__opt.__val_));
|
||||||
__opt.__val_.~value_type();
|
__opt.__val_.~value_type();
|
||||||
}
|
}
|
||||||
swap(this->__engaged_, __opt.__engaged_);
|
swap(this->__engaged_, __opt.__engaged_);
|
||||||
@@ -901,4 +906,4 @@ _LIBCPP_END_NAMESPACE_STD
|
|||||||
|
|
||||||
#endif // _LIBCPP_STD_VER > 11
|
#endif // _LIBCPP_STD_VER > 11
|
||||||
|
|
||||||
#endif // _LIBCPP_OPTIONAL
|
#endif // _LIBCPP_EXPERIMENTAL_OPTIONAL
|
||||||
|
|||||||
@@ -19,6 +19,14 @@
|
|||||||
|
|
||||||
using std::experimental::optional;
|
using std::experimental::optional;
|
||||||
|
|
||||||
|
struct AllowConstAssign {
|
||||||
|
AllowConstAssign() = default;
|
||||||
|
AllowConstAssign(AllowConstAssign const&) {}
|
||||||
|
AllowConstAssign const& operator=(AllowConstAssign const&) const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct X
|
struct X
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -52,6 +60,11 @@ int main()
|
|||||||
assert(static_cast<bool>(opt) == true);
|
assert(static_cast<bool>(opt) == true);
|
||||||
assert(*opt == i);
|
assert(*opt == i);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
optional<const AllowConstAssign> opt;
|
||||||
|
const AllowConstAssign other;
|
||||||
|
opt = other;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
optional<std::unique_ptr<int>> opt;
|
optional<std::unique_ptr<int>> opt;
|
||||||
opt = std::unique_ptr<int>(new int(3));
|
opt = std::unique_ptr<int>(new int(3));
|
||||||
|
|||||||
@@ -19,6 +19,13 @@
|
|||||||
|
|
||||||
using std::experimental::optional;
|
using std::experimental::optional;
|
||||||
|
|
||||||
|
struct AllowConstAssign {
|
||||||
|
AllowConstAssign(AllowConstAssign const&) {}
|
||||||
|
AllowConstAssign const& operator=(AllowConstAssign const&) const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct X
|
struct X
|
||||||
{
|
{
|
||||||
static bool throw_now;
|
static bool throw_now;
|
||||||
@@ -42,6 +49,11 @@ int main()
|
|||||||
static_assert(static_cast<bool>(opt2) == false, "");
|
static_assert(static_cast<bool>(opt2) == false, "");
|
||||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
optional<const AllowConstAssign> opt;
|
||||||
|
optional<const AllowConstAssign> opt2;
|
||||||
|
opt = opt2;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
optional<int> opt;
|
optional<int> opt;
|
||||||
constexpr optional<int> opt2(2);
|
constexpr optional<int> opt2(2);
|
||||||
|
|||||||
@@ -80,6 +80,12 @@ int main()
|
|||||||
assert(static_cast<bool>(opt) == true);
|
assert(static_cast<bool>(opt) == true);
|
||||||
assert(*opt == 1);
|
assert(*opt == 1);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
optional<const int> opt(2);
|
||||||
|
opt.emplace(1);
|
||||||
|
assert(static_cast<bool>(opt) == true);
|
||||||
|
assert(*opt == 1);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
optional<X> opt;
|
optional<X> opt;
|
||||||
opt.emplace();
|
opt.emplace();
|
||||||
|
|||||||
@@ -81,6 +81,17 @@ int main()
|
|||||||
assert(*opt == X({1, 2}));
|
assert(*opt == X({1, 2}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
X::dtor_called = false;
|
||||||
|
{
|
||||||
|
X x;
|
||||||
|
{
|
||||||
|
optional<const X> opt(x);
|
||||||
|
assert(X::dtor_called == false);
|
||||||
|
opt.emplace({1, 2});
|
||||||
|
assert(X::dtor_called == true);
|
||||||
|
assert(*opt == X({1, 2}));
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
optional<std::vector<int>> opt;
|
optional<std::vector<int>> opt;
|
||||||
opt.emplace({1, 2, 3}, std::allocator<int>());
|
opt.emplace({1, 2, 3}, std::allocator<int>());
|
||||||
|
|||||||
@@ -21,6 +21,13 @@
|
|||||||
|
|
||||||
using std::experimental::optional;
|
using std::experimental::optional;
|
||||||
|
|
||||||
|
struct AllowConstAssign {
|
||||||
|
AllowConstAssign(AllowConstAssign const&) {}
|
||||||
|
AllowConstAssign const& operator=(AllowConstAssign const&) const {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct X
|
struct X
|
||||||
{
|
{
|
||||||
static bool throw_now;
|
static bool throw_now;
|
||||||
@@ -76,6 +83,11 @@ int main()
|
|||||||
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
|
||||||
assert(*opt == *opt2);
|
assert(*opt == *opt2);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
optional<const AllowConstAssign> opt;
|
||||||
|
optional<const AllowConstAssign> opt2;
|
||||||
|
opt = std::move(opt2);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
|
static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
|
||||||
optional<X> opt;
|
optional<X> opt;
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ int main()
|
|||||||
optional<T> rhs(3);
|
optional<T> rhs(3);
|
||||||
test(rhs);
|
test(rhs);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef const int T;
|
||||||
|
optional<T> rhs(3);
|
||||||
|
test(rhs);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
typedef X T;
|
typedef X T;
|
||||||
optional<T> rhs;
|
optional<T> rhs;
|
||||||
@@ -97,6 +102,11 @@ int main()
|
|||||||
optional<T> rhs(X(3));
|
optional<T> rhs(X(3));
|
||||||
test(rhs);
|
test(rhs);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef const X T;
|
||||||
|
optional<T> rhs(X(3));
|
||||||
|
test(rhs);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
typedef Y T;
|
typedef Y T;
|
||||||
optional<T> rhs;
|
optional<T> rhs;
|
||||||
|
|||||||
@@ -74,6 +74,17 @@ public:
|
|||||||
friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
|
friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ConstMovable
|
||||||
|
{
|
||||||
|
int i_;
|
||||||
|
public:
|
||||||
|
ConstMovable(int i) : i_(i) {}
|
||||||
|
ConstMovable(const ConstMovable&& x) : i_(x.i_) {}
|
||||||
|
~ConstMovable() {i_ = 0;}
|
||||||
|
friend bool operator==(const ConstMovable& x, const ConstMovable& y) {return x.i_ == y.i_;}
|
||||||
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -86,6 +97,11 @@ int main()
|
|||||||
optional<T> rhs(3);
|
optional<T> rhs(3);
|
||||||
test(rhs);
|
test(rhs);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef const int T;
|
||||||
|
optional<T> rhs(3);
|
||||||
|
test(rhs);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
typedef X T;
|
typedef X T;
|
||||||
optional<T> rhs;
|
optional<T> rhs;
|
||||||
@@ -96,6 +112,11 @@ int main()
|
|||||||
optional<T> rhs(X(3));
|
optional<T> rhs(X(3));
|
||||||
test(rhs);
|
test(rhs);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef const ConstMovable T;
|
||||||
|
optional<T> rhs(ConstMovable(3));
|
||||||
|
test(rhs);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
typedef Y T;
|
typedef Y T;
|
||||||
optional<T> rhs;
|
optional<T> rhs;
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ public:
|
|||||||
friend void swap(Z& x, Z& y) {throw 6;}
|
friend void swap(Z& x, Z& y) {throw 6;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ConstSwappable {
|
||||||
|
};
|
||||||
|
void swap(ConstSwappable const&, ConstSwappable const&) {}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -112,6 +116,11 @@ int main()
|
|||||||
assert(static_cast<bool>(opt2) == true);
|
assert(static_cast<bool>(opt2) == true);
|
||||||
assert(*opt2 == 1);
|
assert(*opt2 == 1);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
optional<const ConstSwappable> opt;
|
||||||
|
optional<const ConstSwappable> opt2;
|
||||||
|
opt.swap(opt2);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
optional<X> opt1;
|
optional<X> opt1;
|
||||||
optional<X> opt2;
|
optional<X> opt2;
|
||||||
|
|||||||
Reference in New Issue
Block a user