diff --git a/libcxx/include/valarray b/libcxx/include/valarray --- a/libcxx/include/valarray +++ b/libcxx/include/valarray @@ -923,10 +923,10 @@ #endif // _LIBCPP_CXX03_LANG // unary operators: - valarray operator+() const; - valarray operator-() const; - valarray operator~() const; - valarray operator!() const; + __val_expr<_UnaryOp<__unary_plus<_Tp>, const valarray&> > operator+() const; + __val_expr<_UnaryOp, const valarray&> > operator-() const; + __val_expr<_UnaryOp<__bit_not<_Tp>, const valarray&> > operator~() const; + __val_expr<_UnaryOp, const valarray&> > operator!() const; // computed assignment: _LIBCPP_INLINE_VISIBILITY @@ -3300,63 +3300,35 @@ #endif // _LIBCPP_CXX03_LANG template -valarray<_Tp> +__val_expr<_UnaryOp<__unary_plus<_Tp>, const valarray<_Tp>&> > valarray<_Tp>::operator+() const { - valarray __r; - size_t __n = size(); - if (__n) - { - __r.__begin_ = __r.__end_ = allocator().allocate(__n); - for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) - ::new ((void*)__r.__end_) value_type(+*__p); - } - return __r; + typedef _UnaryOp<__unary_plus<_Tp>, const valarray<_Tp>&> _Op; + return __val_expr<_Op>(_Op(__unary_plus<_Tp>(), *this)); } template -valarray<_Tp> +__val_expr<_UnaryOp, const valarray<_Tp>&> > valarray<_Tp>::operator-() const { - valarray __r; - size_t __n = size(); - if (__n) - { - __r.__begin_ = __r.__end_ = allocator().allocate(__n); - for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) - ::new ((void*)__r.__end_) value_type(-*__p); - } - return __r; + typedef _UnaryOp, const valarray<_Tp>&> _Op; + return __val_expr<_Op>(_Op(negate<_Tp>(), *this)); } template -valarray<_Tp> +__val_expr<_UnaryOp<__bit_not<_Tp>, const valarray<_Tp>&> > valarray<_Tp>::operator~() const { - valarray __r; - size_t __n = size(); - if (__n) - { - __r.__begin_ = __r.__end_ = allocator().allocate(__n); - for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) - ::new ((void*)__r.__end_) value_type(~*__p); - } - return __r; + typedef _UnaryOp<__bit_not<_Tp>, const valarray<_Tp>&> _Op; + return __val_expr<_Op>(_Op(__bit_not<_Tp>(), *this)); } template -valarray +__val_expr<_UnaryOp, const valarray<_Tp>&> > valarray<_Tp>::operator!() const { - valarray __r; - size_t __n = size(); - if (__n) - { - __r.__begin_ = __r.__end_ = allocator().allocate(__n); - for (const value_type* __p = __begin_; __n; ++__r.__end_, ++__p, --__n) - ::new ((void*)__r.__end_) bool(!*__p); - } - return __r; + typedef _UnaryOp, const valarray<_Tp>&> _Op; + return __val_expr<_Op>(_Op(logical_not<_Tp>(), *this)); } template diff --git a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/bit_not.pass.cpp b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/bit_not.pass.cpp --- a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/bit_not.pass.cpp +++ b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/bit_not.pass.cpp @@ -54,6 +54,13 @@ for (std::size_t i = 0; i < v2.size(); ++i) assert(v2[i] == ~(2*v[i])); } + { + // Make sure we don't have dangling reference problems with unary expressions + std::valarray a = {1, 2, 3}; + std::valarray b = {1, 2, 3}; + auto c = ~a * b; + assert(c.size() == 3); + } - return 0; + return 0; } diff --git a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/negate.pass.cpp b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/negate.pass.cpp --- a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/negate.pass.cpp +++ b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/negate.pass.cpp @@ -64,6 +64,13 @@ for (std::size_t i = 0; i < v2.size(); ++i) assert(v2[i] == -2*v[i]); } + { + // Make sure we don't have dangling reference problems with unary expressions + std::valarray a = {1, 2, 3}; + std::valarray b = {1, 2, 3}; + auto c = -a * b; + assert(c.size() == 3); + } - return 0; + return 0; } diff --git a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/not.pass.cpp b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/not.pass.cpp --- a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/not.pass.cpp +++ b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/not.pass.cpp @@ -40,6 +40,13 @@ for (std::size_t i = 0; i < v2.size(); ++i) assert(v2[i] == !(v[i] + v[i])); } + { + // Make sure we don't have dangling reference problems with unary expressions + std::valarray a = {true, false, true}; + std::valarray b = {true, false, true}; + auto c = !a && b; + assert(c.size() == 3); + } - return 0; + return 0; } diff --git a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/plus.pass.cpp b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/plus.pass.cpp --- a/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/plus.pass.cpp +++ b/libcxx/test/std/numerics/numarray/template.valarray/valarray.unary/plus.pass.cpp @@ -64,6 +64,13 @@ for (std::size_t i = 0; i < v2.size(); ++i) assert(v2[i] == +2*v[i]); } + { + // Make sure we don't have dangling reference problems with unary expressions + std::valarray a = {1, 2, 3}; + std::valarray b = {1, 2, 3}; + auto c = +a * b; + assert(c.size() == 3); + } - return 0; + return 0; }