From: Jonathan Wakely Date: Mon, 8 Jun 2020 17:08:14 +0000 (+0100) Subject: libstdc++: Implement operator<< for std::unique_ptr (LWG 2948) X-Git-Tag: releases/gcc-10.2.0~63 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86e99e8e4f07699dc1f2df93cc7ebd4fe568fc7b;p=thirdparty%2Fgcc.git 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. * testsuite/20_util/default_delete/48631_neg.cc: Adjust dg-error line number. * testsuite/20_util/default_delete/void_neg.cc: Likewise. (cherry picked from commit 187da2ce31f13b2f75d5bb780e30ee364ead9d1d) --- diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 3695214808b7..d0e4cefadd7e 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/default_delete/48631_neg.cc b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc index 6da5a52e28b0..0e807c7d57a0 100644 --- a/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc +++ b/libstdc++-v3/testsuite/20_util/default_delete/48631_neg.cc @@ -26,4 +26,4 @@ struct D : B { }; D d; std::default_delete db; typedef decltype(db(&d)) type; // { dg-error "no match" } -// { dg-error "no type" "" { target *-*-* } 115 } +// { dg-error "no type" "" { target *-*-* } 116 } diff --git a/libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc b/libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc index 149b699d1061..9f281373b37d 100644 --- a/libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc +++ b/libstdc++-v3/testsuite/20_util/default_delete/void_neg.cc @@ -25,5 +25,5 @@ void test01() { std::default_delete d; d(nullptr); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 80 } + // { dg-error "incomplete" "" { target *-*-* } 81 } } 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 000000000000..3f4e4dfabe7c --- /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(); +}