From 187da2ce31f13b2f75d5bb780e30ee364ead9d1d Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 8 Jun 2020 18:08:14 +0100 Subject: [PATCH] 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. --- libstdc++-v3/include/bits/unique_ptr.h | 20 ++++- .../testsuite/20_util/unique_ptr/io/lwg2948.cc | 91 ++++++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/unique_ptr/io/lwg2948.cc 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 #if __cplusplus > 201703L # include +# include #endif namespace std _GLIBCXX_VISIBILITY(default) @@ -934,7 +935,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public __uniq_ptr_hash> { }; -#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 + 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +template + concept streamable = requires (S& o, const T& p) { o << p; }; + +template + bool + check(const std::unique_ptr& p) + { + std::ostringstream ss1, ss2; + ss1 << p; + ss2 << p.get(); + return ss1.str() == ss2.str(); + } + +void +test01() +{ + static_assert( streamable> ); + + std::unique_ptr p; + VERIFY( check(p) ); + p = std::make_unique(); + VERIFY( check(p) ); +} + +template + 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 + int + operator<<(std::basic_ostream& o, typename deleter::pointer&&) + { + o << C{'P'}; + return 1; // no requirement that this operator returns the stream + } + +template + using Unique_ptr = std::unique_ptr; + +static_assert( streamable>> ); +static_assert( ! streamable>> ); +static_assert( ! streamable>> ); +static_assert( streamable>> ); + +void +test02() +{ + Unique_ptr> p; + VERIFY( check(p) ); +} + +int +main() +{ + test01(); + test02(); +} -- 2.7.4