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.
This commit is contained in:
Jonathan Wakely 2020-06-08 18:08:14 +01:00
parent 5fceefeee9
commit 187da2ce31
2 changed files with 109 additions and 2 deletions

View File

@ -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

View File

@ -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();
}