diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2020-06-08 18:08:14 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-06-08 21:21:31 +0100 |
commit | 187da2ce31f13b2f75d5bb780e30ee364ead9d1d (patch) | |
tree | 482cad27ff516b46352fe99b3e484627c7475cc6 | |
parent | 5fceefeee9a10cfba621d215f011a58badc246ad (diff) | |
download | gcc-187da2ce31f13b2f75d5bb780e30ee364ead9d1d.zip gcc-187da2ce31f13b2f75d5bb780e30ee364ead9d1d.tar.gz gcc-187da2ce31f13b2f75d5bb780e30ee364ead9d1d.tar.bz2 |
libstdc++: Implement operator<< for std::unique_ptr (LWG 2948)
libstdc++-v3/ChangeLog:
* include/bits/unique_ptr.h (operator<<): Define for C++20.
* testsuite/20_util/unique_ptr/io/lwg2948.cc: New test.
-rw-r--r-- | libstdc++-v3/include/bits/unique_ptr.h | 20 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/unique_ptr/io/lwg2948.cc | 91 |
2 files changed, 109 insertions, 2 deletions
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 3695214..d0e4cef 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -39,6 +39,7 @@ #include <bits/functional_hash.h> #if __cplusplus > 201703L # include <compare> +# include <ostream> #endif namespace std _GLIBCXX_VISIBILITY(default) @@ -934,7 +935,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>> { }; -#if __cplusplus > 201103L +#if __cplusplus >= 201402L /// @relates unique_ptr @{ #define __cpp_lib_make_unique 201304 @@ -971,7 +972,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename _MakeUniq<_Tp>::__invalid_type make_unique(_Args&&...) = delete; // @} relates unique_ptr -#endif +#endif // C++14 + +#if __cplusplus > 201703L && __cpp_concepts + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2948. unique_ptr does not define operator<< for stream output + /// Stream output operator for unique_ptr + template<typename _CharT, typename _Traits, typename _Tp, typename _Dp> + inline basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, + const unique_ptr<_Tp, _Dp>& __p) + requires requires { __os << __p.get(); } + { + __os << __p.get(); + return __os; + } +#endif // C++20 // @} group pointer_abstractions diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/io/lwg2948.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/io/lwg2948.cc new file mode 100644 index 0000000..3f4e4df --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/io/lwg2948.cc @@ -0,0 +1,91 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include <memory> +#include <sstream> +#include <testsuite_hooks.h> + +template<typename S, typename T> + concept streamable = requires (S& o, const T& p) { o << p; }; + +template<typename T, typename D> + bool + check(const std::unique_ptr<T, D>& p) + { + std::ostringstream ss1, ss2; + ss1 << p; + ss2 << p.get(); + return ss1.str() == ss2.str(); + } + +void +test01() +{ + static_assert( streamable<std::ostream, std::unique_ptr<int>> ); + + std::unique_ptr<int> p; + VERIFY( check(p) ); + p = std::make_unique<int>(); + VERIFY( check(p) ); +} + +template<typename> + struct deleter + { + struct pointer + { + pointer() { } + pointer(std::nullptr_t) { } + explicit operator bool() const { return false; } + bool operator==(pointer) const { return true; } + }; + + void operator()(pointer) const { } + }; + +template<typename C, typename Traits> + int + operator<<(std::basic_ostream<C, Traits>& o, typename deleter<C>::pointer&&) + { + o << C{'P'}; + return 1; // no requirement that this operator returns the stream + } + +template<typename D> + using Unique_ptr = std::unique_ptr<typename D::pointer, D>; + +static_assert( streamable<std::ostream, Unique_ptr<deleter<char>>> ); +static_assert( ! streamable<std::ostream, Unique_ptr<deleter<wchar_t>>> ); +static_assert( ! streamable<std::wostream, Unique_ptr<deleter<char>>> ); +static_assert( streamable<std::wostream, Unique_ptr<deleter<wchar_t>>> ); + +void +test02() +{ + Unique_ptr<deleter<char>> p; + VERIFY( check(p) ); +} + +int +main() +{ + test01(); + test02(); +} |