blob: c3e0d421d19f3f30a13b658bf15ab77e2f1ff99b [file] [log] [blame]
// { dg-do run { target c++11 } }
// { dg-additional-options "-pthread" { target pthread } }
// { dg-require-gthreads "" }
#include <thread>
#include <ostream>
#include <format>
void
test_no_includes(std::ostream& out)
{
std::thread::id i{};
// Check stream insertion works without including <sstream>:
out << i;
#if __cpp_lib_formatters >= 202302
// PR libstdc++/115099 - compilation error: format thread::id
// Verify we can use std::thread::id with std::format without <sstream>:
(void) std::format("{}", i);
#ifdef _GLIBCXX_USE_WCHAR_T
(void) std::format(L"{}", i);
#endif
#endif
}
#include <sstream>
#include <testsuite_hooks.h>
void
test01()
{
std::ostringstream out;
std::thread::id i{}, j{};
out << i;
auto s0 = out.str();
VERIFY( s0 == "thread::id of a non-executing thread" );
out.str("");
out << j;
VERIFY( out.str() == s0 );
std::thread t1([]{});
j = t1.get_id();
out.str("");
out << j;
auto s1 = out.str();
VERIFY( s1 != s0 );
auto j2 = j;
out.str("");
out << j2;
VERIFY( out.str() == s1 );
std::thread t2([]{});
j2 = t2.get_id();
out.str("");
out << j2;
auto s2 = out.str();
VERIFY( s2 != s0 );
VERIFY( s2 != s1 );
#ifdef _GLIBCXX_USE_WCHAR_T
std::wostringstream wout;
wout << i;
auto ws0 = wout.str();
wout.str(L"");
wout << j;
auto ws1 = wout.str();
wout.str(L"");
wout << j2;
auto ws2 = wout.str();
wout.str(L"");
wout << s0.c_str() << ' ' << s1.c_str() << ' ' << s2.c_str();
VERIFY( wout.str() == (ws0 + L' ' + ws1 + L' ' + ws2) );
#endif
t1.join();
t2.join();
}
void
test02()
{
#if __cpp_lib_formatters >= 202302
static_assert( std::is_default_constructible_v<std::formatter<std::thread::id, char>> );
std::thread t1([]{});
std::thread t2([]{});
std::ostringstream out;
std::thread::id i{};
std::thread::id j = t1.get_id();
std::thread::id k = t2.get_id();
out << i << ' ' << j << ' ' << k;
VERIFY( std::format("{} {} {}", i, j, k) == out.str() );
out.str("");
out << j;
auto s1 = out.str();
auto len = s1.size();
out.str("");
std::string s2;
// with width
s2 = std::format("{0:{1}}", j, len + 2);
VERIFY( s2 == (" " + s1) );
// with align + width
s2 = std::format("{0:>{1}}", j, len + 2);
VERIFY( s2 == (" " + s1) );
s2 = std::format("{0:<{1}}", j, len + 2);
VERIFY( s2 == (s1 + " ") );
// with fill-and-align + width
s2 = std::format("{0:x^{1}}", j, len + 5);
VERIFY( s2 == ("xx" + s1 + "xxx") );
#ifdef _GLIBCXX_USE_WCHAR_T
static_assert( std::is_default_constructible_v<std::formatter<std::thread::id, wchar_t>> );
auto ws1 = std::format(L"{}", j);
VERIFY( ws1.length() == len );
#endif
out.str("");
out << i;
s1 = out.str();
len = s1.size();
out.str("");
// with width
s2 = std::format("{0:{1}}", i, len + 2);
VERIFY( s2 == (" " + s1) );
// with align + width
s2 = std::format("{0:>{1}}", i, len + 2);
VERIFY( s2 == (" " + s1) );
s2 = std::format("{0:<{1}}", i, len + 2);
VERIFY( s2 == (s1 + " ") );
// with fill-and-align + width
s2 = std::format("{0:x^{1}}", i, len + 5);
VERIFY( s2 == ("xx" + s1 + "xxx") );
#ifdef _GLIBCXX_USE_WCHAR_T
static_assert( std::is_default_constructible_v<std::formatter<std::thread::id, wchar_t>> );
ws1 = std::format(L"{}", i);
VERIFY( ws1.length() == len );
#endif
t1.join();
t2.join();
static_assert( std::formattable<std::thread::id, char> );
static_assert( std::formattable<std::thread::id, wchar_t> );
static_assert( !std::formattable<std::thread::id, char16_t> );
static_assert( !std::formattable<std::thread::id, int> );
#elif __cplusplus >= 202302L
# error "Feature-test macro for formatters has wrong value in <thread>"
#endif
}
#if __cplusplus >= 202302L
static_assert(std::enable_nonlocking_formatter_optimization<std::thread::id>);
#endif
int main()
{
test01();
test02();
}