LoginSignup
0
0

More than 1 year has passed since last update.

33.6 Mutual exclusion [thread.mutex] C++N4910:2022 (712) p1708.cpp

Posted at

はじめに(Introduction)

N4910 Working Draft, Standard for Programming Language C++

C++ n4910は、ISO/IEC JTC1 SC22 WG21の作業原案(Working Draft)です。
公式のISO/IEC 14882原本ではありません。
ISO/IEC JTC1 SC22 のWG21を含むいくつかのWGでは、可能な限り作業文書を公開し、幅広い意見を求めています。

ISO/IEC JTC1 SC7からISO/IEC JTC1 SC22リエゾンとして、2000年頃、C/C++の品質向上に貢献しようとした活動をしていたことがあります。その頃は、まだISO/IEC TS 17961の原案が出る前です。Cの精神が優勢で、セキュリティ対策は補助的な位置付けでした。ISO/IEC TS 17961の制定と、C/C++のライブラリ類の見直しと、C++の進化はどんどん進んでいきます。 

進化の具合が、どちらに行こうとしているかは、コンパイルて実行させてみないとわかりません。C/C++の規格案の電子ファイルは、そのままコンパイルできる形式であるとよいと主張してきました。MISRA-C/C++, CERTC/C++でも同様です。MISRA-C/C++は、Example Suiteという形で、コード断片をコンパイルできる形で提供するようになりました。

一連の記事はコード断片をコンパイルできる形にする方法を検討してコンパイル、リンク、実行して、規格案の原文と処理系(g++, Clang++)との違いを確認し、技術内容を検討し、ISO/IEC JTC1 SC22 WG21にフィードバックするために用います。
また、CERT C++, MISRA C++等のコーディング標準のコード断片をコンパイルする際の参考にさせていただこうと考えています。CERT C++, MISRA C++が標準化の動きとの時間的なずれがあれば確認できれば幸いです。また、boostライブラリとの関連、Linux OS, 箱庭プロジェクト、g++(GCC), clang++(LLVM)との関係も調査中です。
何か、抜け漏れ、耳より情報がありましたらおしらせくださると幸いです。

背景(back ground)

C/C++でコンパイルエラーが出ると、途方にくれることがしばしばあります。
何回かに1回は、該当するエラーが検索できます。
ただ、条件が違っていて、そこでの修正方法では目的を達成しないこともしばしばです。いろいろな条件のコンパイルエラーとその対応方法について、広く記録することによって、いつか同じエラーに遭遇した時にやくに立つことを目指しています。

この半年の間で、三度、自分のネットでの記録に助けられたことがあります。
また過去に解決できなかった記録を10種類以上、最近になって解決できたことがあります。それは、主に次の3つの情報に基づいています。

cpprefjp - C++日本語リファレンス

コンパイラの実装状況

また
https://researchmap.jp/joub9b3my-1797580/#_1797580
に記載したサイトのお世話になっています。

作業方針(sequence)

Clang++では-std=c++03, C++2bの2種類
g++では-std=c++03, c++2bの2種類
でコンパイルし、

1)コンパイルエラーを収集する。
2)コンパイルエラーをなくす方法を検討する。
コンパイルエラーになる例を示すだけが目的のコードは、コンパイルエラーをなくすのではなく、コンパイルエラーの種類を収集するだけにする。
文法を示すのが目的のコード場合に、コンパイルエラーをなくすのに手間がかかる場合は、順次作業します。
3)リンクエラーをなくす方法を検討する。
文法を示すのが目的のコード場合に、リンクエラーをなくすのに手間がかかる場合は、順次作業します。
4)意味のある出力を作る。
コンパイル、リンクが通っても、意味のある出力を示そうとすると、コンパイル・リンクエラーが出て収拾できそうにない場合がある。順次作業します。

1)だけのものから4)まで進んだものと色々ある状態です。一歩でも前に進むご助言をお待ちしています。「検討事項」の欄に現状を記録するようにしています。

C++N4910:2022 Standard Working Draft on ISO/IEC 14882(0) sample code compile list

bash
$ docker run -v /Users/ogawakiyoshi/n4910:/Users/ogawakiyoshi/n4910 -it kaizenjapan/n4910 /bin/bash

C++N4741, 2018 Standard Working Draft on ISO/IEC 14882 sample code compile list

C++N4606, 2016符号断片編纂一覧(example code compile list)

C++N4606, 2016 Working Draft 2016, ISO/IEC 14882, C++ standard(1) Example code compile list
https://qiita.com/kaizen_nagoya/items/df5d62c35bd6ed1c3d43/

C++N3242, 2011 sample code compile list on clang++ and g++

読書感想文

CコンパイラによるC言語規格の読書感想文として掲載しています。

コンパイル実験が、C++N4910に対する、G++とClang++による感想文だということご理解いただけると幸いです。

読書感想文は人間かAIだけが作るものとは限りません。
本(電子書籍を含む)を入力として、その内容に対する文字列を読書感想文として受け止めましょう。
元の文章をあり方、コンパイルできるように電子化しておくこと、コンパイラが解釈可能な断片の作り方など。

個人開発

Cコンパイラの試験を一人でもくもくとやっているのは個人開発の一つの姿です。

<この項は書きかけです。順次追記します。>

編纂器(Compiler)

clang++ --version

20220826 以前

Debian clang version 14.0.5-++20220610033153+c12386ae247c-1~exp1~20220610153237.151
Target: x86_64-pc-linux-gnu, Thread model: posix, InstalledDir: /usr/bin

20220827 以降

Debian clang version 14.0.6-++20220622053050+f28c006a5895-1~exp1~20220622173135.152
Target: x86_64-pc-linux-gnu Thread model: posix InstalledDir: /usr/bin

g++- --version

g++ (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

算譜(source code)

p16.cpp
// C++N4910 Committee Draft, Standard for Programming Language C++
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf
const char * n4910 = "";
// Debian clang version 14.0.5-++20220610033153+c12386ae247c-
// g++ (GCC) 12.1.0 Copyright (C) 2022 Free Software Foundation, Inc.
// Edited by Dr. OGAWA Kiyoshi. Compile procedure and results record.
// C++N4910:2022 Standard Working Draft on ISO/IEC 14882(0) sample code compile list
// https://qiita.com/kaizen_nagoya/items/fc957ddddd402004bb91

#include "N4910.h"
#include <shared_mutex>

using namespace std;

// 33.6.1 General [thread.mutex.general]
//  Subclause 33.6 provides mechanisms for mutual exclusion: mutexes, locks, and call once. These mechanisms ease the production of race-free programs (6.9.2).
// 33.6.2 Header <mutex> synopsis [mutex.syn]
namespace std {
// 33.6.4.2.2, class mutex
class mutex;
// 33.6.4.2.3, class recursive_mutex
class recursive_mutex;
// 33.6.4.3.2 class timed_mutex
class timed_mutex;
// 33.6.4.3.3, class recursive_timed_mutex class recursive_timed_mutex;
// — resource_unavailable_try_again — if any native handle type manipulated is not available.
// — operation_not_permitted — if the thread does not have the privilege to perform the operation.
// — invalid_argument — if any native handle type manipulated as part of mutex construction is incorrect.
struct defer_lock_t {
    explicit defer_lock_t() = default;
};
struct try_to_lock_t {
    explicit try_to_lock_t() = default;
};
struct adopt_lock_t {
    explicit adopt_lock_t() = default;
};
inline constexpr defer_lock_t  defer_lock { };
inline constexpr try_to_lock_t try_to_lock { };
inline constexpr adopt_lock_t  adopt_lock { };
// 33.6.5, locks
template<class Mutex> class lock_guard;
template<class... MutexTypes> class scoped_lock;
template<class Mutex> class unique_lock;
template<class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
// 33.6.6, generic locking algorithms
template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
struct once_flag;
template<class Callable, class... Args>
void call_once(once_flag& flag, Callable&& func, Args&&... args);
}
// 33.6.3 Header <shared_mutex> synopsis
namespace std {
// 33.6.4.4.2, class shared_mutex
class shared_mutex;
// 33.6.4.5.2, class shared_timed_mutex class shared_timed_mutex;
// 33.6.5.5, class template shared_lock template<class Mutex> class shared_lock; template<class Mutex>
void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
}
// 33.6.4 Mutex requirements [thread.mutex.requirements]
// 33.6.4.1 In general [thread.mutex.requirements.general]
//  A mutex object facilitates protection against data races and allows safe synchronization of data between execution agents (33.2.5). An execution agent owns a mutex from the time it successfully calls one of the lock functions until it calls unlock. Mutexes can be either recursive or non-recursive, and can grant simultaneous ownership to one or many execution agents. Both recursive and non-recursive mutexes are supplied.
// 33.6.4.2 Mutex types [thread.mutex.requirements.mutex]
// 33.6.4.2.1 General [thread.mutex.requirements.mutex.general]
//  The mutex types are the standard library types mutex, recursive_mutex, timed_mutex, recursive_timed_- mutex, shared_mutex, and shared_timed_mutex. They meet the requirements set out in 33.6.4.2. In this description, m denotes an object of a mutex type.
// [Note 1: The mutex types meet the Cpp17Lockable requirements (33.2.5.3).
//  The mutex types meet Cpp17DefaultConstructible and Cpp17Destructible. If initialization of an object of a mutex type fails, an exception of type system_error is thrown. The mutex types are neither copyable nor movable.
//  The error conditions for error codes, if any, reported by member functions of the mutex types are as follows:
// Preconditions: If m is of type mutex, timed_mutex, shared_mutex, or shared_timed_mutex, the calling thread does not own the mutex.
// Effects: Blocks the calling thread until ownership of the mutex can be obtained for the calling thread. Synchronization: Prior unlock() operations on the same object synchronize with (6.9.2) this operation.
// Postconditions: The calling thread owns the mutex.
// Return type: void.
// Throws: system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if the thread does not have the privilege to perform the operation.
// Preconditions: The calling thread owns the mutex.
// Effects: Releases the calling thread’s ownership of the mutex.
// Return type: void.
// Synchronization: This operation synchronizes with (6.9.2) subsequent lock operations that obtain ownership on the same object.
//  The implementation provides lock and unlock operations, as described below. For purposes of determining the existence of a data race, these behave as atomic operations (6.9.2). The lock and unlock operations on a single mutex appears to occur in a single total order.
// [Note 2: This can be viewed as the modification order (6.9.2) of the mutex.
// [Note 3: Construction and destruction of an object of a mutex type need not be thread-safe; other synchronization can be used to ensure that mutex objects are initialized and visible to other threads.
//  The expression m.lock() is well-formed and has the following semantics:
// — resource_deadlock_would_occur — if the implementation detects that a deadlock would occur. 13 The expression m.try_lock() is well-formed and has the following semantics:
// Preconditions: If m is of type mutex, timed_mutex, shared_mutex, or shared_timed_mutex, the calling thread does not own the mutex.
// Effects: Attempts to obtain ownership of the mutex for the calling thread without blocking. If ownership is not obtained, there is no effect and try_lock() immediately returns. An implementation may fail to obtain the lock even if it is not held by any other thread.
// [Note 4: This spurious failure is normally uncommon, but allows interesting implementations based on a simple compare and exchange (33.5).
// An implementation should ensure that try_lock() does not consistently return false in the absence of contending mutex acquisitions.
// Synchronization: If try_lock() returns true, prior unlock() operations on the same object synchronize with (6.9.2) this operation.
// [Note 5: Since lock() does not synchronize with a failed subsequent try_lock(), the visibility rules are weak enough that little would be known about the state after a failure, even in the absence of spurious failures.
// Return type: bool.
// Returns: true if ownership was obtained, otherwise false. Throws: Nothing.
//  The expression m.unlock() is well-formed and has the following semantics:
// Throws: Nothing.
// 33.6.4.2.2 Class mutex [thread.mutex.class]
namespace std {
class mutex {
public:
    constexpr mutex() noexcept;
    ~mutex();
// — it destroys a recursive_mutex object owned by any thread or — a thread terminates while owning a recursive_mutex object.
};
}
mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
void lock();
bool try_lock();
void unlock();
using native_handle_type = implementation-defined;
native_handle_type native_handle();
// see 33.2.3 // see 33.2.3
//  The class mutex provides a non-recursive mutex with exclusive ownership semantics. If one thread owns a mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock()) until the owning thread has released ownership with a call to unlock().
//  [Note 1: After a thread A has called unlock(), releasing a mutex, it is possible for another thread B to lock the same mutex, observe that it is no longer in use, unlock it, and destroy it, before thread A appears to have returned from its unlock call. Implementations are required to handle such scenarios correctly, as long as thread A doesn’t access the mutex after the unlock call returns. These cases typically occur when a reference-counted object contains a mutex that is used to protect the reference count.
//  The class mutex meets all of the mutex requirements (33.6.4). It is a standard-layout class (11.2).
//  [Note 2: A program can deadlock if the thread that owns a mutex object calls lock() on that object. If the implementation can detect the deadlock, a resource_deadlock_would_occur error condition might be observed.
// The behavior of a program is undefined if it destroys a mutex object owned by any thread or a thread terminates while owning a mutex object.
// 33.6.4.2.3 Class recursive_mutex [thread.mutex.recursive]
namespace std {
class recursive_mutex {
public:
    recursive_mutex();
    ~recursive_mutex();
    recursive_mutex(const recursive_mutex&) = delete;
    recursive_mutex& operator=(const recursive_mutex&) = delete;
    void lock();
    bool try_lock() noexcept;
    void unlock();
    using native_handle_type = implementation-defined;
    native_handle_type native_handle();
};
}
// see 33.2.3 // see 33.2.3
//  The class recursive_mutex provides a recursive mutex with exclusive ownership semantics. If one thread owns a recursive_mutex object, attempts by another thread to acquire ownership of that object will fail for try_lock()) or block (for lock()) until the first thread has completely released ownership.
//  The class recursive_mutex meets all of the mutex requirements (33.6.4). It is a standard-layout class (11.2).
//  A thread that owns a recursive_mutex object may acquire additional levels of ownership by calling lock() or try_lock() on that object. It is unspecified how many levels of ownership may be acquired by a single thread. If a thread has already acquired the maximum level of ownership for a recursive_mutex object, additional calls to try_lock() fail, and additional calls to lock() throw an exception of type system_error. A thread shall call unlock() once for each level of ownership acquired by calls to lock() and try_lock(). Only when all levels of ownership have been released may ownership be acquired by another thread.
// The behavior of a program is undefined if:
// Preconditions: If m is of type timed_mutex or shared_timed_mutex, the calling thread does not own the mutex.
// Effects: The function attempts to obtain ownership of the mutex. If abs_time has already passed, the function attempts to obtain ownership without blocking (as if by calling try_lock()). The function returns before the absolute timeout (33.2.4) specified by abs_time only if it has obtained ownership of the mutex object.
// [Note 3: As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
// Synchronization: If try_lock_until() returns true, prior unlock() operations on the same object synchronize with (6.9.2) this operation.
// Return type: bool.
// Returns: true if ownership was obtained, otherwise false. Throws: Timeout-related exceptions (33.2.4).
// 33.6.4.3 Timed mutex types [thread.timedmutex.requirements]
// 33.6.4.3.1 General [thread.timedmutex.requirements.general]
//  The timed mutex types are the standard library types timed_mutex, recursive_timed_mutex, and shared_- timed_mutex. They meet the requirements set out below. In this description, m denotes an object of a mutex type, rel_time denotes an object of an instantiation of duration (29.5), and abs_time denotes an object of an instantiation of time_point (29.6).
// [Note 1: The timed mutex types meet the Cpp17TimedLockable requirements (33.2.5.4). —end note]
//  The expression m.try_lock_for(rel_time) is well-formed and has the following semantics:
// Preconditions: If m is of type timed_mutex or shared_timed_mutex, the calling thread does not own the mutex.
// Effects: The function attempts to obtain ownership of the mutex within the relative timeout (33.2.4) specified by rel_time. If the time specified by rel_time is less than or equal to rel_time.zero(), the function attempts to obtain ownership without blocking (as if by calling try_lock()). The function returns within the timeout specified by rel_time only if it has obtained ownership of the mutex object.
// [Note 2: As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
// Synchronization: If try_lock_for() returns true, prior unlock() operations on the same object synchronize with (6.9.2) this operation.
// Return type: bool.
// Returns: true if ownership was obtained, otherwise false. Throws: Timeout-related exceptions (33.2.4).
//  The expression m.try_lock_until(abs_time) is well-formed and has the following semantics:
// 33.6.4.3.2 Class timed_mutex [thread.timedmutex.class]
namespace std {
class timed_mutex {
public:
    timed_mutex();
    ~timed_mutex();
    timed_mutex(const timed_mutex&) = delete;
    timed_mutex& operator=(const timed_mutex&) = delete;
    void lock(); // blocking
    bool try_lock();
    template<class Rep, class Period>
    bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
    template<class Clock, class Duration>
    bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
    void unlock();
// — it destroys a timed_mutex object owned by any thread,
// — a thread that owns a timed_mutex object calls lock(), try_lock(), try_lock_for(), or try_lock_- until() on that object, or
// — a thread terminates while owning a timed_mutex object.
};
}
using native_handle_type = implementation-defined;
native_handle_type native_handle();
// see 33.2.3 // see 33.2.3
// ownership semantics. If one thread owns a timed_mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock(), try_lock_for(), and try_lock_until()) until the owning thread has released ownership with a call to unlock() or the call to try_lock_for() or try_lock_until() times out (having failed to obtain ownership).
//  The class timed_mutex meets all of the timed mutex requirements (33.6.4.3). It is a standard-layout class (11.2).
//  The behavior of a program is undefined if:
// 33.6.4.3.3 Class recursive_timed_mutex [thread.timedmutex.recursive]
namespace std {
class recursive_timed_mutex {
public:
    recursive_timed_mutex();
    ~recursive_timed_mutex();
    recursive_timed_mutex(const recursive_timed_mutex&) = delete;
    recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
    void lock(); // blocking
    bool try_lock() noexcept;
    template<class Rep, class Period>
    bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
    template<class Clock, class Duration>
    bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
    void unlock();
    using native_handle_type = implementation-defined; // see 33.2.3
    native_handle_type native_handle(); // see 33.2.3
};
}
//  The class recursive_timed_mutex provides a recursive mutex with exclusive ownership semantics. If one thread owns a recursive_timed_mutex object, attempts by another thread to acquire ownership of that object will fail (for try_lock()) or block (for lock(), try_lock_for(), and try_lock_until()) until the owning thread has completely released ownership or the call to try_lock_for() or try_lock_until() times out (having failed to obtain ownership).
//  The class recursive_timed_mutex meets all of the timed mutex requirements (33.6.4.3). It is a standard- layout class (11.2).
// A thread that owns a recursive_timed_mutex object may acquire additional levels of ownership by calling lock(), try_lock(), try_lock_for(), or try_lock_until() on that object. It is unspecified how many levels of ownership may be acquired by a single thread. If a thread has already acquired the maximum level of ownership for a recursive_timed_mutex object, additional calls to try_lock(), try_lock_for(), or try_- lock_until() fail, and additional calls to lock() throw an exception of type system_error. A thread shall call unlock() once for each level of ownership acquired by calls to lock(), try_lock(), try_lock_for(), and try_lock_until(). Only when all levels of ownership have been released may ownership of the object be acquired by another thread.
//  The behavior of a program is undefined if:
// — it destroys a recursive_timed_mutex object owned by any thread, or
// Preconditions: The calling thread has no ownership of the mutex.
// Effects: Blocks the calling thread until shared ownership of the mutex can be obtained for the calling thread. If an exception is thrown then a shared lock has not been acquired for the current thread. Synchronization: Prior unlock() operations on the same object synchronize with (6.9.2) this operation. Postconditions: The calling thread has a shared lock on the mutex.
// Return type: void.
// Throws: system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if the thread does not have the privilege to perform the operation.
// Throws: Nothing.
// Preconditions: The calling thread has no ownership of the mutex.
// Effects: Attempts to obtain shared ownership of the mutex for the calling thread without blocking. If shared ownership is not obtained, there is no effect and try_lock_shared() immediately returns. An implementation may fail to obtain the lock even if it is not held by any other thread.
// Synchronization: If try_lock_shared() returns true, prior unlock() operations on the same object synchronize with (6.9.2) this operation.
// Return type: bool.
// Returns: true if the shared lock was acquired, otherwise false. Throws: Nothing.
// — a thread terminates while owning a recursive_timed_mutex object.
// 33.6.4.4 Shared mutex types [thread.sharedmutex.requirements]
// 33.6.4.4.1 General [thread.sharedmutex.requirements.general]
//  The standard library types shared_mutex and shared_timed_mutex are shared mutex types. Shared mutex types meet the requirements of mutex types (33.6.4.2) and additionally meet the requirements set out below. In this description, m denotes an object of a shared mutex type.
// [Note 1: The shared mutex types meet the Cpp17SharedLockable requirements (33.2.5.5).
//  In addition to the exclusive lock ownership mode specified in 33.6.4.2, shared mutex types provide a shared lock ownership mode. Multiple execution agents can simultaneously hold a shared lock ownership of a shared mutex type. But no execution agent holds a shared lock while another execution agent holds an exclusive lock on the same shared mutex type, and vice-versa. The maximum number of execution agents which can share a shared lock on a single shared mutex type is unspecified, but is at least 10000. If more than the maximum number of execution agents attempt to obtain a shared lock, the excess execution agents block until the number of shared locks are reduced below the maximum amount by other execution agents releasing their shared lock.
// The expression m.lock_shared() is well-formed and has the following semantics:
// — resource_deadlock_would_occur — if the implementation detects that a deadlock would occur. 11 The expression m.unlock_shared() is well-formed and has the following semantics:
// Preconditions: The calling thread holds a shared lock on the mutex.
// Effects: Releases a shared lock on the mutex held by the calling thread.
// Return type: void.
// Synchronization: This operation synchronizes with (6.9.2) subsequent lock() operations that obtain ownership on the same object.
//  The expression m.try_lock_shared() is well-formed and has the following semantics:
// 33.6.4.4.2 Class shared_mutex [thread.sharedmutex.class]
namespace std {
class shared_mutex {
public:
    shared_mutex();
// — it destroys a shared_mutex object owned by any thread,
// — a thread attempts to recursively gain any ownership of a shared_mutex, or // — a thread terminates while possessing any ownership of a shared_mutex.
};
}
~shared_mutex();
shared_mutex(const shared_mutex&) = delete;
shared_mutex& operator=(const shared_mutex&) = delete;
// exclusive ownership
void lock();
bool try_lock();
void unlock();
// shared ownership
void lock_shared();
bool try_lock_shared();
void unlock_shared();
// blocking
// blocking
using native_handle_type = implementation-defined;
native_handle_type native_handle();
// see 33.2.3 // see 33.2.3
//  The class shared_mutex provides a non-recursive mutex with shared ownership semantics.
//  The class shared_mutex meets all of the shared mutex requirements (33.6.4.4). It is a standard-layout class (11.2).
// The behavior of a program is undefined if:
//  shared_mutex may be a synonym for shared_timed_mutex.
// 33.6.4.5 Shared timed mutex types [thread.sharedtimedmutex.requirements]
// 33.6.4.5.1 General [thread.sharedtimedmutex.requirements.general]
//  The standard library type shared_timed_mutex is a shared timed mutex type. Shared timed mutex types meet the requirements of timed mutex types (33.6.4.3), shared mutex types (33.6.4.4), and additionally meet the requirements set out below. In this description, m denotes an object of a shared timed mutex type, rel_time denotes an object of an instantiation of duration (29.5), and abs_time denotes an object of an instantiation of time_point (29.6).
// [Note 1: The shared timed mutex types meet the Cpp17SharedTimedLockable requirements (33.2.5.6).
// The expression m.try_lock_shared_for(rel_time) is well-formed and has the following semantics:
// Preconditions: The calling thread has no ownership of the mutex.
// Effects: Attempts to obtain shared lock ownership for the calling thread within the relative timeout (33.2.4) specified by rel_time. If the time specified by rel_time is less than or equal to rel_- time.zero(), the function attempts to obtain ownership without blocking (as if by calling try_lock_- shared()). The function returns within the timeout specified by rel_time only if it has obtained shared ownership of the mutex object.
// [Note 2: As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
// If an exception is thrown then a shared lock has not been acquired for the current thread. Synchronization: If try_lock_shared_for() returns true, prior unlock() operations on the same object synchronize with (6.9.2) this operation.
// Return type: bool.
// Returns: true if the shared lock was acquired, otherwise false.
// Throws: Timeout-related exceptions (33.2.4).
//  The expression m.try_lock_shared_until(abs_time) is well-formed and has the following semantics:
// Preconditions: The calling thread has no ownership of the mutex.
// Effects: The function attempts to obtain shared ownership of the mutex. If abs_time has already passed, the function attempts to obtain shared ownership without blocking (as if by calling try_lock_- shared()). The function returns before the absolute timeout (33.2.4) specified by abs_time only if it has obtained shared ownership of the mutex object.
// [Note 3: As with try_lock(), there is no guarantee that ownership will be obtained if the lock is available, but implementations are expected to make a strong effort to do so.
// If an exception is thrown then a shared lock has not been acquired for the current thread. Synchronization: If try_lock_shared_until() returns true, prior unlock() operations on the same object synchronize with (6.9.2) this operation.
// Return type: bool.
// Returns: true if the shared lock was acquired, otherwise false.
// Throws: Timeout-related exceptions (33.2.4).
// 33.6.4.5.2 Class shared_timed_mutex [thread.sharedtimedmutex.class]
namespace std {
class shared_timed_mutex {
public:
    shared_timed_mutex();
    ~shared_timed_mutex();
    shared_timed_mutex(const shared_timed_mutex&) = delete;
    shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
// exclusive ownership
    void lock(); // blocking
    bool try_lock();
    template<class Rep, class Period>
    bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
    template<class Clock, class Duration>
    bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
    void unlock();
// shared ownership
    void lock_shared(); // blocking
    bool try_lock_shared();
    template<class Rep, class Period>
    bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
    template<class Clock, class Duration>
    bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
    void unlock_shared();
};
}
//  The class shared_timed_mutex provides a non-recursive mutex with shared ownership semantics.
// The class shared_timed_mutex meets all of the shared timed mutex requirements (33.6.4.5). It is a standard-layout class (11.2).
//  The behavior of a program is undefined if:
// — it destroys a shared_timed_mutex object owned by any thread,
// — a thread attempts to recursively gain any ownership of a shared_timed_mutex, or — a thread terminates while possessing any ownership of a shared_timed_mutex.
//  A lock is an object that holds a reference to a lockable object and may unlock the lockable object during the lock’s destruction (such as when leaving block scope). An execution agent may use a lock to aid in managing ownership of a lockable object in an exception safe manner. A lock is said to own a lockable object if it is  currently managing the ownership of that lockable object for an execution agent. A lock does not manage the lifetime of the lockable object it references.
// 33.6.5 Locks [thread.lock]
// 33.6.5.1 General [thread.lock.general]
// Effects: Initializes pm with m. Calls m.lock().
// [Note 1: Locks are intended to ease the burden of unlocking the lockable object under both normal and exceptional circumstances.
//  Some lock constructors take tag types which describe what should be done with the lockable object during the lock’s construction.
namespace std {
struct defer_lock_t  { };
struct try_to_lock_t { };
// do not acquire ownership of the mutex // try to acquire ownership of the mutex
// without blocking
// assume the calling thread has already
// obtained mutex ownership and manage it
inline constexpr defer_lock_t
inline constexpr try_to_lock_t  try_to_lock { };
inline constexpr adopt_lock_t   adopt_lock { };
}
// 33.6.5.2 Class template lock_guard [thread.lock.guard]
namespace std {
template<class Mutex>
class lock_guard {
public:
    using mutex_type = Mutex;
    explicit lock_guard(mutex_type& m);
    lock_guard(mutex_type& m, adopt_lock_t);
    ~lock_guard();
    lock_guard(const lock_guard&) = delete;
    lock_guard& operator=(const lock_guard&) = delete;
private:
    mutex_type& pm; // exposition only
};
}
//  An object of type lock_guard controls the ownership of a lockable object within a scope. A lock_guard object maintains ownership of a lockable object throughout the lock_guard object’s lifetime (6.7.3). The behavior of a program is undefined if the lockable object referenced by pm does not exist for the entire lifetime of the lock_guard object. The supplied Mutex type shall meet the Cpp17BasicLockable requirements (33.2.5.2).
struct adopt_lock_t  { };
explicit lock_guard(mutex_type& m);
lock_guard(mutex_type& m, adopt_lock_t);
// Preconditions: The calling thread holds a non-shared lock on m. Effects: Initializes pm with m.
// Throws: Nothing.
~lock_guard();
// Effects: Equivalent to: pm.unlock()
// 33.6.5.3 Class template scoped_lock [thread.lock.scoped]
namespace std {
template<class... MutexTypes>
class scoped_lock {
public:
    using mutex_type = see below ;
// Only if sizeof...(MutexTypes) == 1 is true
    defer_lock { };
// — If sizeof...(MutexTypes) is one, let Mutex denote the sole type constituting the pack MutexTypes. Mutex shall meet the Cpp17BasicLockable requirements (33.2.5.2). The member typedef-name mutex_- type denotes the same type as Mutex.
// — Otherwise, all types in the template parameter pack MutexTypes shall meet the Cpp17Lockable requirements (33.2.5.3) and there is no member mutex_type.
    explicit scoped_lock(MutexTypes&... m);
    explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
    ~scoped_lock();
    scoped_lock(const scoped_lock&) = delete;
    scoped_lock& operator=(const scoped_lock&) = delete;
private:
    tuple<MutexTypes&...> pm; // exposition only
};
}
//  An object of type scoped_lock controls the ownership of lockable objects within a scope. A scoped_lock object maintains ownership of lockable objects throughout the scoped_lock object’s lifetime (6.7.3). The behavior of a program is undefined if the lockable objects referenced by pm do not exist for the entire lifetime of the scoped_lock object.
explicit scoped_lock(MutexTypes&... m);
// Effects: Initializes pm with tie(m...). Then if sizeof...(MutexTypes) is 0, no effects. Otherwise if sizeof...(MutexTypes) is 1, then m.lock(). Otherwise, lock(m...).
explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
// Preconditions: The calling thread holds a non-shared lock on each element of m. Effects: Initializes pm with tie(m...).
// Throws: Nothing.
~scoped_lock();
// Effects: For all i in [0, sizeof...(MutexTypes)), get<i>(pm).unlock().
// 33.6.5.4 Class template unique_lock [thread.lock.unique]
// 33.6.5.4.1 General [thread.lock.unique.general]
namespace std {
template<class Mutex>
class unique_lock {
public:
    using mutex_type = Mutex;
// 33.6.5.4.2, construct/copy/destroy
    unique_lock() noexcept;
    explicit unique_lock(mutex_type& m);
    unique_lock(mutex_type& m, defer_lock_t) noexcept;
    unique_lock(mutex_type& m, try_to_lock_t);
    unique_lock(mutex_type& m, adopt_lock_t);
    template<class Clock, class Duration>
    unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
    template<class Rep, class Period>
    unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
    ~unique_lock();
    unique_lock(const unique_lock&) = delete;
    unique_lock& operator=(const unique_lock&) = delete;
    unique_lock(unique_lock&& u) noexcept;
    unique_lock& operator=(unique_lock&& u);
// Postconditions: pm == 0 and owns == false.
// 33.6.5.4.3, locking void lock();
    bool try_lock();
    template<class Rep, class Period>
    bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
    template<class Clock, class Duration>
    bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
    void unlock();
// 33.6.5.4.4, modifiers
    void swap(unique_lock& u) noexcept;
    mutex_type* release() noexcept;
// 33.6.5.4.5, observers
    bool owns_lock() const noexcept;
    explicit operator bool () const noexcept;
    mutex_type* mutex() const noexcept;
private:
    mutex_type* pm; // exposition only bool owns; // exposition only
};
}
//  An object of type unique_lock controls the ownership of a lockable object within a scope. Ownership of the lockable object may be acquired at construction or after construction, and may be transferred, after acquisition, to another unique_lock object. Objects of type unique_lock are not copyable but are movable. The behavior of a program is undefined if the contained pointer pm is not null and the lockable object pointed to by pm does not exist for the entire remaining lifetime (6.7.3) of the unique_lock object. The supplied Mutex type shall meet the Cpp17BasicLockable requirements (33.2.5.2).
//  [Note 1: unique_lock<Mutex> meets the Cpp17BasicLockable requirements. If Mutex meets the Cpp17Lockable requirements (33.2.5.3), unique_lock<Mutex> also meets the Cpp17Lockable requirements; if Mutex meets the Cpp17TimedLockable requirements (33.2.5.4), unique_lock<Mutex> also meets the Cpp17TimedLockable requirements.
// 33.6.5.4.2 Constructors, destructor, and assignment [thread.lock.unique.cons]
unique_lock() noexcept;
explicit unique_lock(mutex_type& m);
// Effects: Calls m.lock().
// Postconditions: pm == addressof(m) and owns == true.
unique_lock(mutex_type& m, defer_lock_t) noexcept;
// Postconditions: pm == addressof(m) and owns == false.
unique_lock(mutex_type& m, try_to_lock_t);
// Preconditions: The supplied Mutex type meets the Cpp17Lockable requirements (33.2.5.3). Effects: Calls m.try_lock().
// Postconditions: pm == addressof(m) and owns == res, where res is the value returned by the call to m.try_lock().
unique_lock(mutex_type& m, adopt_lock_t);
// Preconditions: The calling thread holds a non-shared lock on m.
// Postconditions: pm == addressof(m) and owns == true. Throws: Nothing.
template<class Clock, class Duration>
unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
// Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements (33.2.5.4). Effects: Calls m.try_lock_until(abs_time).
// Postconditions: pm == addressof(m) and owns == res, where res is the value returned by the call to m.try_lock_until(abs_time).
template<class Rep, class Period>
unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
// Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements (33.2.5.4). Effects: Calls m.try_lock_for(rel_time).
// Postconditions: pm == addressof(m) and owns == res, where res is the value returned by the call to m.try_lock_for(rel_time).
unique_lock(unique_lock&& u) noexcept;
// Postconditions: pm == u_p.pm and owns == u_p.owns (where u_p is the state of u just prior to this construction), u.pm == 0 and u.owns == false.
unique_lock& operator=(unique_lock&& u);
// Effects: If owns calls pm->unlock().
// Postconditions: pm == u_p.pm and owns == u_p.owns (where u_p is the state of u just prior to this construction), u.pm == 0 and u.owns == false.
// [Note 1 : With a recursive mutex it is possible for both *this and u to own the same mutex before the assignment. In this case, *this will own the mutex after the assignment and u will not. // Throws: Nothing.
~unique_lock();
// Effects: If owns calls pm->unlock().
// 33.6.5.4.3 Locking [thread.lock.unique.locking]
void lock();
// Effects: As if by pm->lock().
// Postconditions: owns == true.
// Throws: Any exception thrown by pm->lock(). system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if pm is nullptr.
// — resource_deadlock_would_occur — if on entry owns is true.
bool try_lock();
// Preconditions: The supplied Mutex meets the Cpp17Lockable requirements (33.2.5.3). Effects: As if by pm->try_lock().
// Postconditions: owns == res, where res is the value returned by the call to try_lock(). Returns: The value returned by the call to try_lock().
// Throws: Any exception thrown by pm->try_lock(). system_error when an exception is required (33.2.2).
// Error conditions:
// — operation_not_permitted — if pm is nullptr.
// — resource_deadlock_would_occur — if on entry owns is true.
template<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
// Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements (33.2.5.4). Effects: As if by pm->try_lock_until(abs_time).
// Postconditions: owns == res, where res is the value returned by the call to try_lock_until(abs_- time).
// Returns: The value returned by the call to try_lock_until(abs_time).
// Throws: Any exception thrown by pm->try_lock_until(). system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if pm is nullptr.
// — resource_deadlock_would_occur — if on entry owns is true.
template<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
// Preconditions: The supplied Mutex type meets the Cpp17TimedLockable requirements (33.2.5.4). Effects: As if by pm->try_lock_for(rel_time).
// Postconditions: owns == res, where res is the value returned by the call to try_lock_for(rel_time). Returns: The value returned by the call to try_lock_for(rel_time).
// Throws: Any exception thrown by pm->try_lock_for(). system_error when an exception is required (33.2.2).
// Error conditions:
// — operation_not_permitted — if pm is nullptr.
// — resource_deadlock_would_occur — if on entry owns is true.
void unlock();
// Effects: As if by pm->unlock().
// Postconditions: owns == false.
// Throws: system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if on entry owns is false. 33.6.5.4.4 Modifiers
void swap(unique_lock& u) noexcept;
[thread.lock.unique.mod]
// Effects: Swaps the data members of *this and u.
mutex_type* release() noexcept;
// Postconditions: pm == 0 and owns == false. Returns: The previous value of pm.
template<class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
// Effects: As if by x.swap(y).
// 33.6.5.4.5 Observers [thread.lock.unique.obs]
bool owns_lock() const noexcept;
// Returns: owns.
explicit operator bool() const noexcept;
// Returns: owns. § 33.6.5.4.5
mutex_type *mutex() const noexcept;
// Returns: pm.
// 33.6.5.5 Class template shared_lock
// 33.6.5.5.1 General
namespace std {
template<class Mutex>
class shared_lock {
public:
    using mutex_type = Mutex;
// 33.6.5.5.2, construct/copy/destroy
    shared_lock() noexcept;
    explicit shared_lock(mutex_type& m);
    shared_lock(mutex_type& m, defer_lock_t) noexcept;
    shared_lock(mutex_type& m, try_to_lock_t);
    shared_lock(mutex_type& m, adopt_lock_t);
    template<class Clock, class Duration>
    shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
    template<class Rep, class Period>
    shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
    ~shared_lock();
    shared_lock(const shared_lock&) = delete;
    shared_lock& operator=(const shared_lock&) = delete;
    shared_lock(shared_lock&& u) noexcept;
    shared_lock& operator=(shared_lock&& u) noexcept;
// 33.6.5.5.3, locking [thread.lock.shared.locking]
    void lock(); // blocking
    bool try_lock();
    template<class Rep, class Period>
    bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
    template<class Clock, class Duration>
    bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
    void unlock();
// 33.6.5.5.4, modifiers
    void swap(shared_lock& u) noexcept;
    mutex_type* release() noexcept;
// 33.6.5.5.5, observers
    bool owns_lock() const noexcept;
    explicit operator bool () const noexcept;
    mutex_type* mutex() const noexcept;
private:
    mutex_type* pm;
    bool owns;
};
}
// exposition only // exposition only
//  An object of type shared_lock controls the shared ownership of a lockable object within a scope. Shared ownership of the lockable object may be acquired at construction or after construction, and may be transferred, after acquisition, to another shared_lock object. Objects of type shared_lock are not copyable but are movable. The behavior of a program is undefined if the contained pointer pm is not null and the lockable object pointed to by pm does not exist for the entire remaining lifetime (6.7.3) of the shared_lock object. The supplied Mutex type shall meet the Cpp17SharedLockable requirements (33.2.5.5).
//  [Note 1: shared_lock<Mutex> meets the Cpp17Lockable requirements (33.2.5.3). If Mutex meets the Cpp17Shared- TimedLockable requirements (33.2.5.6), shared_lock<Mutex> also meets the Cpp17TimedLockable requirements (33.2.5.4).
// blocking
explicit shared_lock(mutex_type& m);
// 33.6.5.5.2 Constructors, destructor, and assignment [thread.lock.shared.cons]
shared_lock() noexcept;
// Postconditions: pm == nullptr and owns == false.
// Effects: Calls m.lock_shared().
// Postconditions: pm == addressof(m) and owns == true.
shared_lock(mutex_type& m, defer_lock_t) noexcept;
// Postconditions: pm == addressof(m) and owns == false.
shared_lock(mutex_type& m, try_to_lock_t);
// Effects: Calls m.try_lock_shared().
// Postconditions: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared().
shared_lock(mutex_type& m, adopt_lock_t);
// Preconditions: The calling thread holds a shared lock on m. Postconditions: pm == addressof(m) and owns == true.
template<class Clock, class Duration>
shared_lock(mutex_type& m,
            const chrono::time_point<Clock, Duration>& abs_time);
// Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements (33.2.5.6). Effects: Calls m.try_lock_shared_until(abs_time).
// Postconditions: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared_until(abs_time).
template<class Rep, class Period>
shared_lock(mutex_type& m,
            const chrono::duration<Rep, Period>& rel_time);
// Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements (33.2.5.6). Effects: Calls m.try_lock_shared_for(rel_time).
// Postconditions: pm == addressof(m) and owns == res where res is the value returned by the call to m.try_lock_shared_for(rel_time).
~shared_lock();
// Effects: If owns calls pm->unlock_shared().
shared_lock(shared_lock&& sl) noexcept;
// Postconditions: pm == sl_p.pm and owns == sl_p.owns (where sl_p is the state of sl just prior to this construction), sl.pm == nullptr and sl.owns == false.
shared_lock& operator=(shared_lock&& sl) noexcept;
// Effects: If owns calls pm->unlock_shared().
// Postconditions: pm == sl_p.pm and owns == sl_p.owns (where sl_p is the state of sl just prior to this assignment), sl.pm == nullptr and sl.owns == false.
// 33.6.5.5.3 Locking [thread.lock.shared.locking]
void lock();
// Effects: As if by pm->lock_shared().
// Postconditions: owns == true.
// Throws: Any exception thrown by pm->lock_shared(). system_error when an exception is required (33.2.2).
// Error conditions:
// — operation_not_permitted — if pm is nullptr.
// — resource_deadlock_would_occur — if on entry owns is true.
bool try_lock();
// Effects: As if by pm->try_lock_shared().
// Postconditions: owns == res, where res is the value returned by the call to pm->try_lock_shared().
// Returns: The value returned by the call to pm->try_lock_shared().
// Throws: Any exception thrown by pm->try_lock_shared(). system_error when an exception is required (33.2.2).
// Error conditions:
// — operation_not_permitted — if pm is nullptr.
// — resource_deadlock_would_occur — if on entry owns is true.
template<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
// Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements (33.2.5.6). Effects: As if by pm->try_lock_shared_until(abs_time).
// Postconditions: owns == res, where res is the value returned by the call to pm->try_lock_shared_- until(abs_time).
// Returns: The value returned by the call to pm->try_lock_shared_until(abs_time).
// Throws: Any exception thrown by pm->try_lock_shared_until(abs_time). system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if pm is nullptr.
// // — resource_deadlock_would_occur — if on entry owns is true.
template<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
// Preconditions: Mutex meets the Cpp17SharedTimedLockable requirements (33.2.5.6). Effects: As if by pm->try_lock_shared_for(rel_time).
// Postconditions: owns == res, where res is the value returned by the call to pm->try_lock_shared_- for(rel_time).
// // Returns: The value returned by the call to pm->try_lock_shared_for(rel_time).
// Throws: Any exception thrown by pm->try_lock_shared_for(rel_time). system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if pm is nullptr.
// — resource_deadlock_would_occur — if on entry owns is true.
void unlock();
// Effects: As if by pm->unlock_shared().
// Postconditions: owns == false.
// Throws: system_error when an exception is required (33.2.2). Error conditions:
// — operation_not_permitted — if on entry owns is false.
// 33.6.5.5.4 Modifiers [thread.lock.shared.mod]
void swap(shared_lock& sl) noexcept;
// Effects: Swaps the data members of *this and sl.
mutex_type* release() noexcept;
// Postconditions: pm == nullptr and owns == false. Returns: The previous value of pm.
template<class Mutex>
void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
// Effects: As if by x.swap(y).
// 33.6.5.5.5 Observers [thread.lock.shared.obs]
bool owns_lock() const noexcept;
// Returns: owns.
explicit operator bool() const noexcept;
// Returns: owns.
mutex_type* mutex() const noexcept;
// Returns: pm.
// 33.6.6 Generic locking algorithms [thread.lock.algorithm]
template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
// Preconditions: Each template parameter type meets the Cpp17Lockable requirements.
// [Note 1: The unique_lock class template meets these requirements when suitably instantiated. —end note]
// Effects: Calls try_lock() for each argument in order beginning with the first until all arguments have been processed or a call to try_lock() fails, either by returning false or by throwing an exception. If a call to try_lock() fails, unlock() is called for all prior arguments with no further calls to try_lock().
// Returns: -1 if all calls to try_lock() returned true, otherwise a zero-based index value that indicates the argument for which try_lock() returned false.
template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
// Preconditions: Each template parameter type meets the Cpp17Lockable requirements.
// [Note 2: The unique_lock class template meets these requirements when suitably instantiated.
// Effects: All arguments are locked via a sequence of calls to lock(), try_lock(), or unlock() on each argument. The sequence of calls does not result in deadlock, but is otherwise unspecified.
// [Note 3: A deadlock avoidance algorithm such as try-and-back-off can be used, but the specific algorithm is not specified to avoid over-constraining implementations.
// If a call to lock() or try_lock() throws an exception, unlock() is called for any argument that had been locked by a call to lock() or try_lock().
// 33.6.7 Call once  [thread.once]
// 33.6.7.1 Struct once_flag [thread.once.onceflag]
namespace std {
struct once_flag {
    constexpr once_flag() noexcept;
    once_flag(const once_flag&) = delete;
    once_flag& operator=(const once_flag&) = delete;
};
}
//  The class once_flag is an opaque data structure that call_once uses to initialize data without causing a data race or deadlock.
constexpr once_flag() noexcept;
// Synchronization: The construction of a once_flag object is not synchronized.
// Postconditions: The object’s internal state is set to indicate to an invocation of call_once with the object as its initial argument that no function has been called.
// 33.6.7.2 Function call_once [thread.once.callonce]
template<class Callable, class... Args>
void call_once(once_flag& flag, Callable&& func, Args&&... args);
// Mandates: is_invocable_v<Callable, Args...> is true.
// Effects: An execution of call_once that does not call its func is a passive execution. An execu- tion of call_once that calls its func is an active execution. An active execution calls INVOKE( std::forward<Callable>(func), std::forward<Args>(args)...). If such a call to func throws an exception the execution is exceptional, otherwise it is returning. An exceptional execution propagates the exception to the caller of call_once. Among all executions of call_once for any given once_flag: at most one is a returning execution; if there is a returning execution, it is the last active execution; and there are passive executions only if there is a returning execution.
// [Note 1: Passive executions allow other threads to reliably observe the results produced by the earlier returning execution.
// Synchronization: For any given once_flag: all active executions occur in a total order; completion of an active execution synchronizes with (6.9.2) the start of the next one in this total order; and the returning execution synchronizes with the return from all passive executions.
// Throws: system_error when an exception is required (33.2.2), or any exception thrown by func. [Example 1:
// global flag, regular function
void init();
std::once_flag flag;
void f() {
    std::call_once(flag, init);
}
// function static flag, function object
struct initializer {
    void operator()();
};
void g() {
    static std::once_flag flag2;
    std::call_once(flag2, initializer());
}
// object flag, member function
class information {
    std::once_flag verified;
    void verifier();
public:
    void verify() {
        std::call_once(verified, &information::verifier, *this);
    }
};
int main() {
    cout  <<  n4910 << endl;
    return EXIT_SUCCESS;
}

編纂・実行結果(compile and go)

bash
$ clang++ p1708.cpp -std=03 -o p1708l -I. -Wall
In file included from p1708.cpp:10:
In file included from ./N4910.h:11:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/atomic:38:
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/c++0x_warning.h:32:2: error: This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support \
 ^
p1708.cpp:29:51: warning: defaulted function definitions are a C++11 extension [-Wc++11-extensions]
  struct defer_lock_t { explicit defer_lock_t() = default; };
                                                  ^
p1708.cpp:30:53: warning: defaulted function definitions are a C++11 extension [-Wc++11-extensions]
  struct try_to_lock_t { explicit try_to_lock_t() = default; };
                                                    ^
p1708.cpp:31:51: warning: defaulted function definitions are a C++11 extension [-Wc++11-extensions]
  struct adopt_lock_t { explicit adopt_lock_t() = default; };
                                                  ^
p1708.cpp:32:10: error: unknown type name 'constexpr'
  inline constexpr defer_lock_t  defer_lock { };
         ^
p1708.cpp:32:3: warning: inline variables are a C++17 extension [-Wc++17-extensions]
  inline constexpr defer_lock_t  defer_lock { };
  ^
p1708.cpp:32:32: error: expected ';' after top level declarator
  inline constexpr defer_lock_t  defer_lock { };
                               ^
                               ;
p1708.cpp:33:10: error: unknown type name 'constexpr'
  inline constexpr try_to_lock_t try_to_lock { };
         ^
p1708.cpp:33:3: warning: inline variables are a C++17 extension [-Wc++17-extensions]
  inline constexpr try_to_lock_t try_to_lock { };
  ^
p1708.cpp:33:33: error: expected ';' after top level declarator
  inline constexpr try_to_lock_t try_to_lock { };
                                ^
                                ;
p1708.cpp:34:10: error: unknown type name 'constexpr'
  inline constexpr adopt_lock_t  adopt_lock { };
         ^
p1708.cpp:34:3: warning: inline variables are a C++17 extension [-Wc++17-extensions]
  inline constexpr adopt_lock_t  adopt_lock { };
  ^
p1708.cpp:34:32: error: expected ';' after top level declarator
  inline constexpr adopt_lock_t  adopt_lock { };
                               ^
                               ;
p1708.cpp:36:55: warning: variadic templates are a C++11 extension [-Wc++11-extensions]
template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
                                                      ^
p1708.cpp:38:60: error: expected ';' at end of declaration
    void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
                                                           ^
                                                           ;
p1708.cpp:38:61: error: C++ requires a type specifier for all declarations
    void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
                                                            ^
p1708.cpp:40:35: warning: variadic templates are a C++11 extension [-Wc++11-extensions]
template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
                                  ^
p1708.cpp:40:109: warning: variadic templates are a C++11 extension [-Wc++11-extensions]
template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
                                                                                                            ^
p1708.cpp:42:33: warning: variadic templates are a C++11 extension [-Wc++11-extensions]
  template<class Callable, class... Args>
                                ^
p1708.cpp:43:45: warning: rvalue references are a C++11 extension [-Wc++11-extensions]
    void call_once(once_flag& flag, Callable&& func, Args&&... args);
                                            ^
p1708.cpp:43:58: warning: rvalue references are a C++11 extension [-Wc++11-extensions]
    void call_once(once_flag& flag, Callable&& func, Args&&... args);
                                                         ^
p1708.cpp:51:29: error: unknown type name 'Mutex'; did you mean 'mutex'?
      void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
                            ^~~~~
                            mutex
p1708.cpp:20:7: note: 'mutex' declared here
class mutex;
      ^
p1708.cpp:51:52: error: unknown type name 'Mutex'; did you mean 'mutex'?
      void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
                                                   ^~~~~
                                                   mutex
p1708.cpp:20:7: note: 'mutex' declared here
class mutex;
      ^
p1708.cpp:51:17: error: no template named 'shared_lock'; did you mean 'scoped_lock'?
      void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
                ^~~~~~~~~~~
                scoped_lock
p1708.cpp:36:77: note: 'scoped_lock' declared here
template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
                                                                            ^
p1708.cpp:51:40: error: no template named 'shared_lock'; did you mean 'scoped_lock'?
      void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
                                       ^~~~~~~~~~~
                                       scoped_lock
p1708.cpp:36:77: note: 'scoped_lock' declared here
template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
                                                                            ^
p1708.cpp:51:63: error: expected function body after function declarator
      void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
                                                              ^
p1708.cpp:91:1: error: unknown type name 'constexpr'
constexpr mutex() noexcept; ~mutex();
^
p1708.cpp:91:11: error: constructor cannot have a return type
constexpr mutex() noexcept; ~mutex();
          ^~~~~
p1708.cpp:91:18: error: expected ';' at end of declaration list
constexpr mutex() noexcept; ~mutex();
                 ^
                 ;
p1708.cpp:94:7: error: expected unqualified-id
mutex(const mutex&) = delete;
      ^
p1708.cpp:94:7: error: expected ')'
p1708.cpp:94:6: note: to match this '('
mutex(const mutex&) = delete;
     ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
12 warnings and 20 errors generated.
$ clang++ p1708.cpp -std=2b -o p1708l -I. -Wall
p1708.cpp:29:10: error: redefinition of 'defer_lock_t'
  struct defer_lock_t { explicit defer_lock_t() = default; };
         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_mutex.h:129:10: note: previous definition is here
  struct defer_lock_t { explicit defer_lock_t() = default; };
         ^
p1708.cpp:30:10: error: redefinition of 'try_to_lock_t'
  struct try_to_lock_t { explicit try_to_lock_t() = default; };
         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_mutex.h:132:10: note: previous definition is here
  struct try_to_lock_t { explicit try_to_lock_t() = default; };
         ^
p1708.cpp:31:10: error: redefinition of 'adopt_lock_t'
  struct adopt_lock_t { explicit adopt_lock_t() = default; };
         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_mutex.h:136:10: note: previous definition is here
  struct adopt_lock_t { explicit adopt_lock_t() = default; };
         ^
p1708.cpp:32:34: error: redefinition of 'defer_lock'
  inline constexpr defer_lock_t  defer_lock { };
                                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_mutex.h:139:44: note: previous definition is here
  _GLIBCXX17_INLINE constexpr defer_lock_t      defer_lock { };
                                                ^
p1708.cpp:33:34: error: redefinition of 'try_to_lock'
  inline constexpr try_to_lock_t try_to_lock { };
                                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_mutex.h:142:45: note: previous definition is here
  _GLIBCXX17_INLINE constexpr try_to_lock_t     try_to_lock { };
                                                ^
p1708.cpp:34:34: error: redefinition of 'adopt_lock'
  inline constexpr adopt_lock_t  adopt_lock { };
                                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_mutex.h:145:44: note: previous definition is here
  _GLIBCXX17_INLINE constexpr adopt_lock_t      adopt_lock { };
                                                ^
p1708.cpp:51:29: error: unknown type name 'Mutex'; did you mean 'mutex'?
      void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
                            ^~~~~
                            mutex
p1708.cpp:20:7: note: 'mutex' declared here
class mutex;
      ^
p1708.cpp:51:52: error: unknown type name 'Mutex'; did you mean 'mutex'?
      void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
                                                   ^~~~~
                                                   mutex
p1708.cpp:20:7: note: 'mutex' declared here
class mutex;
      ^
p1708.cpp:89:11: error: redefinition of 'mutex'
    class mutex {
          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_mutex.h:83:9: note: previous definition is here
  class mutex : private __mutex_base
        ^
p1708.cpp:94:7: error: expected unqualified-id
mutex(const mutex&) = delete;
      ^
p1708.cpp:94:7: error: expected ')'
p1708.cpp:94:6: note: to match this '('
mutex(const mutex&) = delete;
     ^
p1708.cpp:95:8: error: overloaded 'operator=' must be a binary operator (has 1 parameter)
mutex& operator=(const mutex&) = delete;
       ^
p1708.cpp:99:28: error: unknown type name 'implementation'
using native_handle_type = implementation-defined; native_handle_type native_handle();
                           ^
p1708.cpp:99:42: error: expected ';' after alias declaration
using native_handle_type = implementation-defined; native_handle_type native_handle();
                                         ^
                                         ;
p1708.cpp:99:52: error: unknown type name 'native_handle_type'
using native_handle_type = implementation-defined; native_handle_type native_handle();
                                                   ^
p1708.cpp:116:28: error: unknown type name 'implementation'
using native_handle_type = implementation-defined; native_handle_type native_handle();
                           ^
p1708.cpp:116:42: error: expected ';' after alias declaration
using native_handle_type = implementation-defined; native_handle_type native_handle();
                                         ^
                                         ;
p1708.cpp:116:52: error: unknown type name 'native_handle_type'
using native_handle_type = implementation-defined; native_handle_type native_handle();
                                                   ^
p1708.cpp:160:28: error: unknown type name 'implementation'
using native_handle_type = implementation-defined; native_handle_type native_handle();
                           ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.

$ g++ p1708.cpp -std=03 -o p1708g -I. -Wall
In file included from /usr/local/include/c++/12.1.0/atomic:38,
                 from N4910.h:11,
                 from p1708.cpp:10:
/usr/local/include/c++/12.1.0/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
   32 | #error This file requires compiler and library support \
      |  ^~~~~
p1708.cpp:32:10: warning: identifier 'constexpr' is a keyword in C++11 [-Wc++11-compat]
   32 |   inline constexpr defer_lock_t  defer_lock { };
      |          ^~~~~~~~~
p1708.cpp:38:61: warning: identifier 'noexcept' is a keyword in C++11 [-Wc++11-compat]
   38 |     void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |                                                             ^~~~~~~~
p1708.cpp:29:51: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   29 |   struct defer_lock_t { explicit defer_lock_t() = default; };
      |                                                   ^~~~~~~
p1708.cpp:30:53: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   30 |   struct try_to_lock_t { explicit try_to_lock_t() = default; };
      |                                                     ^~~~~~~
p1708.cpp:31:51: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   31 |   struct adopt_lock_t { explicit adopt_lock_t() = default; };
      |                                                   ^~~~~~~
p1708.cpp:32:10: error: 'constexpr' does not name a type
   32 |   inline constexpr defer_lock_t  defer_lock { };
      |          ^~~~~~~~~
p1708.cpp:32:10: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:33:10: error: 'constexpr' does not name a type
   33 |   inline constexpr try_to_lock_t try_to_lock { };
      |          ^~~~~~~~~
p1708.cpp:33:10: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:34:10: error: 'constexpr' does not name a type
   34 |   inline constexpr adopt_lock_t  adopt_lock { };
      |          ^~~~~~~~~
p1708.cpp:34:10: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:36:55: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                       ^~~
p1708.cpp:38:61: error: expected initializer before 'noexcept'
   38 |     void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |                                                             ^~~~~~~~
p1708.cpp:40:35: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   40 | template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
      |                                   ^~~
p1708.cpp:40:69: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   40 | template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
      |                                                                     ^~~
p1708.cpp:40:109: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   40 | template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
      |                                                                                                             ^~~
p1708.cpp:40:140: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   40 | template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...); template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
      |                                                                                                                                            ^~~
p1708.cpp:42:33: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   42 |   template<class Callable, class... Args>
      |                                 ^~~
p1708.cpp:43:45: error: expected ',' or '...' before '&&' token
   43 |     void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |                                             ^~
p1708.cpp:51:12: error: variable or field 'swap' declared void
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |            ^~~~
p1708.cpp:51:17: error: 'shared_lock' was not declared in this scope
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                 ^~~~~~~~~~~
p1708.cpp:51:17: note: 'std::shared_lock' is only available from C++14 onwards
p1708.cpp:51:29: error: 'Mutex' was not declared in this scope; did you mean 'mutex'?
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                             ^~~~~
      |                             mutex
p1708.cpp:51:37: error: 'x' was not declared in this scope
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                     ^
p1708.cpp:51:40: error: 'shared_lock' was not declared in this scope
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                        ^~~~~~~~~~~
p1708.cpp:51:40: note: 'std::shared_lock' is only available from C++14 onwards
p1708.cpp:51:52: error: 'Mutex' was not declared in this scope; did you mean 'mutex'?
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                                    ^~~~~
      |                                                    mutex
p1708.cpp:51:60: error: 'y' was not declared in this scope; did you mean 'yn'?
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                                            ^
      |                                                            yn
p1708.cpp:91:1: error: 'constexpr' does not name a type
   91 | constexpr mutex() noexcept; ~mutex();
      | ^~~~~~~~~
p1708.cpp:91:1: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:94:7: error: expected unqualified-id before 'const'
   94 | mutex(const mutex&) = delete;
      |       ^~~~~
p1708.cpp:94:7: error: expected ')' before 'const'
   94 | mutex(const mutex&) = delete;
      |      ~^~~~~
      |       )
p1708.cpp:95:8: error: 'std::mutex& operator=(const std::mutex&)' must be a non-static member function
   95 | mutex& operator=(const mutex&) = delete;
      |        ^~~~~~~~
p1708.cpp:95:34: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
   95 | mutex& operator=(const mutex&) = delete;
      |                                  ^~~~~~
p1708.cpp:99:7: error: expected nested-name-specifier before 'native_handle_type'
   99 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |       ^~~~~~~~~~~~~~~~~~
p1708.cpp:99:52: error: 'native_handle_type' does not name a type
   99 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:111:52: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  111 |          recursive_mutex(const recursive_mutex&) = delete;
      |                                                    ^~~~~~
p1708.cpp:112:63: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  112 |          recursive_mutex& operator=(const recursive_mutex&) = delete;
      |                                                               ^~~~~~
p1708.cpp:114:15: error: expected ';' at end of member declaration
  114 | bool try_lock() noexcept;
      |               ^
      |                ;
p1708.cpp:114:17: error: 'noexcept' does not name a type
  114 | bool try_lock() noexcept;
      |                 ^~~~~~~~
p1708.cpp:114:17: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:116:7: error: expected nested-name-specifier before 'native_handle_type'
  116 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |       ^~~~~~~~~~~~~~~~~~
p1708.cpp:116:52: error: 'native_handle_type' does not name a type
  116 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:147:41: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  147 |       timed_mutex(const timed_mutex&) = delete;
      |                                         ^~~~~~
p1708.cpp:148:52: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  148 |       timed_mutex& operator=(const timed_mutex&) = delete;
      |                                                    ^~~~~~
p1708.cpp:152:33: error: 'chrono' does not name a type
  152 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                 ^~~~~~
p1708.cpp:152:49: error: expected unqualified-id before '<' token
  152 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                                 ^
p1708.cpp:152:49: error: expected ')' before '<' token
  152 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                          ~                      ^
      |                                                 )
p1708.cpp:152:49: error: expected initializer before '<' token
p1708.cpp:154:35: error: 'chrono' does not name a type
  154 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                   ^~~~~~
p1708.cpp:154:53: error: expected unqualified-id before '<' token
  154 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                                     ^
p1708.cpp:154:53: error: expected ')' before '<' token
  154 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                            ~                        ^
      |                                                     )
p1708.cpp:154:53: error: expected initializer before '<' token
p1708.cpp:160:7: error: expected nested-name-specifier before 'native_handle_type'
  160 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |       ^~~~~~~~~~~~~~~~~~
p1708.cpp:160:52: error: 'native_handle_type' does not name a type
  160 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:170:61: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  170 |       recursive_timed_mutex(const recursive_timed_mutex&) = delete;
      |                                                             ^~~~~~
p1708.cpp:171:72: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  171 |       recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
      |                                                                        ^~~~~~
p1708.cpp:173:15: error: expected ';' at end of member declaration
  173 | bool try_lock() noexcept; template<class Rep, class Period>
      |               ^
      |                ;
p1708.cpp:173:17: error: 'noexcept' does not name a type
  173 | bool try_lock() noexcept; template<class Rep, class Period>
      |                 ^~~~~~~~
p1708.cpp:173:17: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:174:33: error: 'chrono' does not name a type
  174 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                 ^~~~~~
p1708.cpp:174:49: error: expected unqualified-id before '<' token
  174 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                                 ^
p1708.cpp:174:49: error: expected ')' before '<' token
  174 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                          ~                      ^
      |                                                 )
p1708.cpp:174:49: error: expected initializer before '<' token
p1708.cpp:176:35: error: 'chrono' does not name a type
  176 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                   ^~~~~~
p1708.cpp:176:53: error: expected unqualified-id before '<' token
  176 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                                     ^
p1708.cpp:176:53: error: expected ')' before '<' token
  176 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                            ~                        ^
      |                                                     )
p1708.cpp:176:53: error: expected initializer before '<' token
p1708.cpp:178:7: error: expected nested-name-specifier before 'native_handle_type'
  178 | using native_handle_type = implementation-defined; // see 33.2.3
      |       ^~~~~~~~~~~~~~~~~~
p1708.cpp:179:1: error: 'native_handle_type' does not name a type
  179 | native_handle_type native_handle(); // see 33.2.3
      | ^~~~~~~~~~~~~~~~~~
p1708.cpp:219:16: error: expected constructor, destructor, or type conversion before ';' token
  219 | ~shared_mutex();
      |                ^
p1708.cpp:220:14: error: expected unqualified-id before 'const'
  220 | shared_mutex(const shared_mutex&) = delete;
      |              ^~~~~
p1708.cpp:220:14: error: expected ')' before 'const'
  220 | shared_mutex(const shared_mutex&) = delete;
      |             ~^~~~~
      |              )
p1708.cpp:221:15: error: 'std::shared_mutex& operator=(const std::shared_mutex&)' must be a non-static member function
  221 | shared_mutex& operator=(const shared_mutex&) = delete;
      |               ^~~~~~~~
p1708.cpp:221:48: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  221 | shared_mutex& operator=(const shared_mutex&) = delete;
      |                                                ^~~~~~
p1708.cpp:232:7: error: expected nested-name-specifier before 'native_handle_type'
  232 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |       ^~~~~~~~~~~~~~~~~~
p1708.cpp:232:52: error: 'native_handle_type' does not name a type
  232 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:263:55: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  263 |       shared_timed_mutex(const shared_timed_mutex&) = delete;
      |                                                       ^~~~~~
p1708.cpp:264:66: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  264 |       shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
      |                                                                  ^~~~~~
p1708.cpp:269:33: error: 'chrono' does not name a type
  269 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                 ^~~~~~
p1708.cpp:269:49: error: expected unqualified-id before '<' token
  269 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                                 ^
p1708.cpp:269:49: error: expected ')' before '<' token
  269 |         bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                          ~                      ^
      |                                                 )
p1708.cpp:269:49: error: expected initializer before '<' token
p1708.cpp:271:35: error: 'chrono' does not name a type
  271 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                   ^~~~~~
p1708.cpp:271:53: error: expected unqualified-id before '<' token
  271 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                                     ^
p1708.cpp:271:53: error: expected ')' before '<' token
  271 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                            ~                        ^
      |                                                     )
p1708.cpp:271:53: error: expected initializer before '<' token
p1708.cpp:277:40: error: 'chrono' does not name a type
  277 |         bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
      |                                        ^~~~~~
p1708.cpp:277:56: error: expected unqualified-id before '<' token
  277 |         bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
      |                                                        ^
p1708.cpp:277:56: error: expected ')' before '<' token
  277 |         bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
      |                                 ~                      ^
      |                                                        )
p1708.cpp:277:56: error: expected initializer before '<' token
p1708.cpp:279:42: error: 'chrono' does not name a type
  279 |         bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                          ^~~~~~
p1708.cpp:279:60: error: expected unqualified-id before '<' token
  279 |         bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                                            ^
p1708.cpp:279:60: error: expected ')' before '<' token
  279 |         bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                   ~                        ^
      |                                                            )
p1708.cpp:279:60: error: expected initializer before '<' token
p1708.cpp:294:10: error: redefinition of 'struct std::defer_lock_t'
  294 |   struct defer_lock_t  { };
      |          ^~~~~~~~~~~~
p1708.cpp:29:10: note: previous definition of 'struct std::defer_lock_t'
   29 |   struct defer_lock_t { explicit defer_lock_t() = default; };
      |          ^~~~~~~~~~~~
p1708.cpp:295:10: error: redefinition of 'struct std::try_to_lock_t'
  295 |   struct try_to_lock_t { };
      |          ^~~~~~~~~~~~~
p1708.cpp:30:10: note: previous definition of 'struct std::try_to_lock_t'
   30 |   struct try_to_lock_t { explicit try_to_lock_t() = default; };
      |          ^~~~~~~~~~~~~
p1708.cpp:300:15: error: 'constexpr' does not name a type
  300 |        inline constexpr defer_lock_t
      |               ^~~~~~~~~
p1708.cpp:300:15: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:302:15: error: 'constexpr' does not name a type
  302 |        inline constexpr adopt_lock_t   adopt_lock { };
      |               ^~~~~~~~~
p1708.cpp:302:15: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:309:16: error: expected nested-name-specifier before 'mutex_type'
  309 |          using mutex_type = Mutex;
      |                ^~~~~~~~~~
p1708.cpp:310:31: error: expected ')' before '&' token
  310 | explicit lock_guard(mutex_type& m); lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard();
      |                    ~          ^
      |                               )
p1708.cpp:310:58: error: expected ')' before '&' token
  310 | explicit lock_guard(mutex_type& m); lock_guard(mutex_type& m, adopt_lock_t); ~lock_guard();
      |                                               ~          ^
      |                                                          )
p1708.cpp:311:42: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  311 |          lock_guard(const lock_guard&) = delete;
      |                                          ^~~~~~
p1708.cpp:312:53: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  312 |          lock_guard& operator=(const lock_guard&) = delete;
      |                                                     ^~~~~~
p1708.cpp:314:1: error: 'mutex_type' does not name a type
  314 | mutex_type& pm; // exposition only
      | ^~~~~~~~~~
p1708.cpp:318:10: error: ISO C++ forbids declaration of 'lock_guard' with no type [-fpermissive]
  318 | explicit lock_guard(mutex_type& m);
      |          ^~~~~~~~~~
p1708.cpp:318:1: error: 'explicit' outside class declaration
  318 | explicit lock_guard(mutex_type& m);
      | ^~~~~~~~
p1708.cpp:318:21: error: 'mutex_type' was not declared in this scope
  318 | explicit lock_guard(mutex_type& m);
      |                     ^~~~~~~~~~
p1708.cpp:318:33: error: 'm' was not declared in this scope; did you mean 'tm'?
  318 | explicit lock_guard(mutex_type& m);
      |                                 ^
      |                                 tm
p1708.cpp:319:11: error: expected constructor, destructor, or type conversion before '(' token
  319 | lock_guard(mutex_type& m, adopt_lock_t);
      |           ^
p1708.cpp:322:12: error: expected class-name before '(' token
  322 | ~lock_guard();
      |            ^
p1708.cpp:326:19: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  326 |     template<class... MutexTypes>
      |                   ^~~
p1708.cpp:329:7: error: expected nested-name-specifier before 'mutex_type'
  329 | using mutex_type = see below ;
      |       ^~~~~~~~~~
p1708.cpp:331:1: error: 'defer_lock' does not name a type; did you mean 'defer_lock_t'?
  331 | defer_lock { };
      | ^~~~~~~~~~
      | defer_lock_t
p1708.cpp:334:37: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  334 | explicit scoped_lock(MutexTypes&... m);
      |                                     ^
p1708.cpp:335:51: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  335 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m); ~scoped_lock();
      |                                                   ^
p1708.cpp:336:44: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  336 |          scoped_lock(const scoped_lock&) = delete;
      |                                            ^~~~~~
p1708.cpp:337:55: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  337 |          scoped_lock& operator=(const scoped_lock&) = delete;
      |                                                       ^~~~~~
p1708.cpp:339:1: error: 'tuple' does not name a type
  339 | tuple<MutexTypes&...> pm; // exposition only
      | ^~~~~
p1708.cpp:342:10: error: ISO C++ forbids declaration of 'scoped_lock' with no type [-fpermissive]
  342 | explicit scoped_lock(MutexTypes&... m);
      |          ^~~~~~~~~~~
p1708.cpp:342:1: error: 'explicit' outside class declaration
  342 | explicit scoped_lock(MutexTypes&... m);
      | ^~~~~~~~
p1708.cpp:342:22: error: 'MutexTypes' was not declared in this scope
  342 | explicit scoped_lock(MutexTypes&... m);
      |                      ^~~~~~~~~~
p1708.cpp:344:10: error: ISO C++ forbids declaration of 'scoped_lock' with no type [-fpermissive]
  344 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
      |          ^~~~~~~~~~~
p1708.cpp:344:1: error: 'explicit' outside class declaration
  344 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
      | ^~~~~~~~
p1708.cpp:344:10: error: redefinition of 'int scoped_lock'
  344 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
      |          ^~~~~~~~~~~
p1708.cpp:342:10: note: 'int scoped_lock' previously defined here
  342 | explicit scoped_lock(MutexTypes&... m);
      |          ^~~~~~~~~~~
p1708.cpp:344:22: error: reference to 'adopt_lock_t' is ambiguous
  344 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
      |                      ^~~~~~~~~~~~
p1708.cpp:31:10: note: candidates are: 'struct std::adopt_lock_t'
   31 |   struct adopt_lock_t { explicit adopt_lock_t() = default; };
      |          ^~~~~~~~~~~~
p1708.cpp:317:8: note:                 'struct adopt_lock_t'
  317 | struct adopt_lock_t  { };
      |        ^~~~~~~~~~~~
p1708.cpp:344:36: error: 'MutexTypes' was not declared in this scope
  344 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
      |                                    ^~~~~~~~~~
p1708.cpp:347:13: error: expected class-name before '(' token
  347 | ~scoped_lock();
      |             ^
p1708.cpp:355:13: error: expected nested-name-specifier before 'mutex_type'
  355 |       using mutex_type = Mutex;
      |             ^~~~~~~~~~
p1708.cpp:357:13: error: expected ';' at end of member declaration
  357 | unique_lock() noexcept;
      |             ^
      |              ;
p1708.cpp:357:15: error: 'noexcept' does not name a type
  357 | unique_lock() noexcept;
      |               ^~~~~~~~
p1708.cpp:357:15: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:358:32: error: expected ')' before '&' token
  358 | explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                     ~          ^
      |                                )
p1708.cpp:358:60: error: expected ')' before '&' token
  358 | explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                                                 ~          ^
      |                                                            )
p1708.cpp:358:111: error: expected ')' before '&' token
  358 | explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                                                                                                    ~          ^
      |                                                                                                               )
p1708.cpp:358:154: error: expected ')' before '&' token
  358 | explicit unique_lock(mutex_type& m); unique_lock(mutex_type& m, defer_lock_t) noexcept; unique_lock(mutex_type& m, try_to_lock_t); unique_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                                                                                                                                               ~          ^
      |                                                                                                                                                          )
p1708.cpp:359:25: error: expected ')' before '&' token
  359 |   unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
      |              ~          ^
      |                         )
p1708.cpp:361:23: error: expected ')' before '&' token
  361 | unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); ~unique_lock();
      |            ~          ^
      |                       )
p1708.cpp:362:35: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  362 | unique_lock(const unique_lock&) = delete;
      |                                   ^~~~~~
p1708.cpp:363:46: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  363 | unique_lock& operator=(const unique_lock&) = delete;
      |                                              ^~~~~~
p1708.cpp:364:24: error: expected ',' or '...' before '&&' token
  364 | unique_lock(unique_lock&& u) noexcept;
      |                        ^~
p1708.cpp:364:1: error: invalid constructor; you probably meant 'std::unique_lock<Mutex> (const std::unique_lock<Mutex>&)'
  364 | unique_lock(unique_lock&& u) noexcept;
      | ^~~~~~~~~~~
p1708.cpp:364:28: error: expected ';' at end of member declaration
  364 | unique_lock(unique_lock&& u) noexcept;
      |                            ^
      |                             ;
p1708.cpp:364:30: error: 'noexcept' does not name a type
  364 | unique_lock(unique_lock&& u) noexcept;
      |                              ^~~~~~~~
p1708.cpp:364:30: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:365:35: error: expected ',' or '...' before '&&' token
  365 | unique_lock& operator=(unique_lock&& u);
      |                                   ^~
p1708.cpp:370:36: error: 'chrono' does not name a type
  370 |            bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                    ^~~~~~
p1708.cpp:370:52: error: expected unqualified-id before '<' token
  370 |            bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                                    ^
p1708.cpp:370:52: error: expected ')' before '<' token
  370 |            bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                             ~                      ^
      |                                                    )
p1708.cpp:370:52: error: expected initializer before '<' token
p1708.cpp:372:38: error: 'chrono' does not name a type
  372 |            bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                      ^~~~~~
p1708.cpp:372:56: error: expected unqualified-id before '<' token
  372 |            bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                                        ^
p1708.cpp:372:56: error: expected ')' before '<' token
  372 |            bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                               ~                        ^
      |                                                        )
p1708.cpp:372:56: error: expected initializer before '<' token
p1708.cpp:375:25: error: expected ';' at end of member declaration
  375 | void swap(unique_lock& u) noexcept; mutex_type* release() noexcept;
      |                         ^
      |                          ;
p1708.cpp:375:27: error: 'noexcept' does not name a type
  375 | void swap(unique_lock& u) noexcept; mutex_type* release() noexcept;
      |                           ^~~~~~~~
p1708.cpp:375:27: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:375:37: error: 'mutex_type' does not name a type
  375 | void swap(unique_lock& u) noexcept; mutex_type* release() noexcept;
      |                                     ^~~~~~~~~~
p1708.cpp:377:18: error: expected ';' at end of member declaration
  377 | bool owns_lock() const noexcept;
      |                  ^~~~~
      |                       ;
p1708.cpp:377:24: error: 'noexcept' does not name a type
  377 | bool owns_lock() const noexcept;
      |                        ^~~~~~~~
p1708.cpp:377:24: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:378:27: warning: explicit conversion operators only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  378 | explicit operator bool () const noexcept; mutex_type* mutex() const noexcept;
      |                           ^~~~~
p1708.cpp:378:27: error: expected ';' at end of member declaration
  378 | explicit operator bool () const noexcept; mutex_type* mutex() const noexcept;
      |                           ^~~~~
      |                                ;
p1708.cpp:378:33: error: 'noexcept' does not name a type
  378 | explicit operator bool () const noexcept; mutex_type* mutex() const noexcept;
      |                                 ^~~~~~~~
p1708.cpp:378:33: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:378:43: error: 'mutex_type' does not name a type
  378 | explicit operator bool () const noexcept; mutex_type* mutex() const noexcept;
      |                                           ^~~~~~~~~~
p1708.cpp:380:1: error: 'mutex_type' does not name a type
  380 | mutex_type* pm; // exposition only bool owns; // exposition only
      | ^~~~~~~~~~
p1708.cpp:385:18: error: expected constructor, destructor, or type conversion before 'noexcept'
  385 |    unique_lock() noexcept;
      |                  ^~~~~~~~
p1708.cpp:386:10: error: ISO C++ forbids declaration of 'unique_lock' with no type [-fpermissive]
  386 | explicit unique_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:386:1: error: 'explicit' outside class declaration
  386 | explicit unique_lock(mutex_type& m);
      | ^~~~~~~~
p1708.cpp:386:22: error: 'mutex_type' was not declared in this scope
  386 | explicit unique_lock(mutex_type& m);
      |                      ^~~~~~~~~~
p1708.cpp:386:34: error: 'm' was not declared in this scope; did you mean 'tm'?
  386 | explicit unique_lock(mutex_type& m);
      |                                  ^
      |                                  tm
p1708.cpp:389:12: error: expected constructor, destructor, or type conversion before '(' token
  389 | unique_lock(mutex_type& m, defer_lock_t) noexcept;
      |            ^
p1708.cpp:391:12: error: expected constructor, destructor, or type conversion before '(' token
  391 | unique_lock(mutex_type& m, try_to_lock_t);
      |            ^
p1708.cpp:394:12: error: expected constructor, destructor, or type conversion before '(' token
  394 | unique_lock(mutex_type& m, adopt_lock_t);
      |            ^
p1708.cpp:398:20: error: expected constructor, destructor, or type conversion before '(' token
  398 |         unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
      |                    ^
p1708.cpp:402:14: error: expected constructor, destructor, or type conversion before '(' token
  402 |   unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
      |              ^
p1708.cpp:405:12: error: expected constructor, destructor, or type conversion before '(' token
  405 | unique_lock(unique_lock&& u) noexcept;
      |            ^
p1708.cpp:407:1: error: reference to 'unique_lock' is ambiguous
  407 | unique_lock& operator=(unique_lock&& u);
      | ^~~~~~~~~~~
p1708.cpp:36:118: note: candidates are: 'template<class Mutex> class std::unique_lock'
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:386:10: note:                 'int unique_lock'
  386 | explicit unique_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:411:13: error: expected class-name before '(' token
  411 | ~unique_lock();
      |             ^
p1708.cpp:428:35: error: 'chrono' does not name a type
  428 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                   ^~~~~~
p1708.cpp:428:53: error: expected unqualified-id before '<' token
  428 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                                     ^
p1708.cpp:428:53: error: expected ')' before '<' token
  428 |         bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                            ~                        ^
      |                                                     )
p1708.cpp:428:53: error: expected initializer before '<' token
p1708.cpp:436:27: error: 'chrono' does not name a type
  436 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                           ^~~~~~
p1708.cpp:436:43: error: expected unqualified-id before '<' token
  436 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                           ^
p1708.cpp:436:43: error: expected ')' before '<' token
  436 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                    ~                      ^
      |                                           )
p1708.cpp:436:43: error: expected initializer before '<' token
p1708.cpp:448:6: error: variable or field 'swap' declared void
  448 | void swap(unique_lock& u) noexcept;
      |      ^~~~
p1708.cpp:448:11: error: reference to 'unique_lock' is ambiguous
  448 | void swap(unique_lock& u) noexcept;
      |           ^~~~~~~~~~~
p1708.cpp:36:118: note: candidates are: 'template<class Mutex> class std::unique_lock'
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:386:10: note:                 'int unique_lock'
  386 | explicit unique_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:448:24: error: 'u' was not declared in this scope
  448 | void swap(unique_lock& u) noexcept;
      |                        ^
p1708.cpp:449:1: error: expected unqualified-id before '[' token
  449 | [thread.lock.unique.mod]
      | ^
p1708.cpp:454:8: error: variable or field 'swap' declared void
  454 |   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |        ^~~~
p1708.cpp:454:13: error: reference to 'unique_lock' is ambiguous
  454 |   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |             ^~~~~~~~~~~
p1708.cpp:36:118: note: candidates are: 'template<class Mutex> class std::unique_lock'
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:386:10: note:                 'int unique_lock'
  386 | explicit unique_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:454:30: error: expected primary-expression before '>' token
  454 |   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |                              ^
p1708.cpp:454:33: error: 'x' was not declared in this scope
  454 |   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |                                 ^
p1708.cpp:454:36: error: reference to 'unique_lock' is ambiguous
  454 |   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |                                    ^~~~~~~~~~~
p1708.cpp:36:118: note: candidates are: 'template<class Mutex> class std::unique_lock'
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:386:10: note:                 'int unique_lock'
  386 | explicit unique_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:454:53: error: expected primary-expression before '>' token
  454 |   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |                                                     ^
p1708.cpp:454:56: error: 'y' was not declared in this scope; did you mean 'yn'?
  454 |   void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept;
      |                                                        ^
      |                                                        yn
p1708.cpp:457:24: error: expected initializer before 'noexcept'
  457 | bool owns_lock() const noexcept;
      |                        ^~~~~~~~
p1708.cpp:459:32: error: expected initializer before 'noexcept'
  459 | explicit operator bool() const noexcept;
      |                                ^~~~~~~~
p1708.cpp:461:1: error: 'mutex_type' does not name a type
  461 | mutex_type *mutex() const noexcept;
      | ^~~~~~~~~~
p1708.cpp:469:13: error: expected nested-name-specifier before 'mutex_type'
  469 |       using mutex_type = Mutex;
      |             ^~~~~~~~~~
p1708.cpp:471:13: error: expected ';' at end of member declaration
  471 | shared_lock() noexcept;
      |             ^
      |              ;
p1708.cpp:471:15: error: 'noexcept' does not name a type
  471 | shared_lock() noexcept;
      |               ^~~~~~~~
p1708.cpp:471:15: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:472:32: error: expected ')' before '&' token
  472 | explicit shared_lock(mutex_type& m); shared_lock(mutex_type& m, defer_lock_t) noexcept; shared_lock(mutex_type& m, try_to_lock_t); shared_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                     ~          ^
      |                                )
p1708.cpp:472:60: error: expected ')' before '&' token
  472 | explicit shared_lock(mutex_type& m); shared_lock(mutex_type& m, defer_lock_t) noexcept; shared_lock(mutex_type& m, try_to_lock_t); shared_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                                                 ~          ^
      |                                                            )
p1708.cpp:472:111: error: expected ')' before '&' token
  472 | explicit shared_lock(mutex_type& m); shared_lock(mutex_type& m, defer_lock_t) noexcept; shared_lock(mutex_type& m, try_to_lock_t); shared_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                                                                                                    ~          ^
      |                                                                                                               )
p1708.cpp:472:154: error: expected ')' before '&' token
  472 | explicit shared_lock(mutex_type& m); shared_lock(mutex_type& m, defer_lock_t) noexcept; shared_lock(mutex_type& m, try_to_lock_t); shared_lock(mutex_type& m, adopt_lock_t); template<class Clock, class Duration>
      |                                                                                                                                               ~          ^
      |                                                                                                                                                          )
p1708.cpp:473:25: error: expected ')' before '&' token
  473 |   shared_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
      |              ~          ^
      |                         )
p1708.cpp:475:23: error: expected ')' before '&' token
  475 | shared_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); ~shared_lock();
      |            ~          ^
      |                       )
p1708.cpp:476:35: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  476 | shared_lock(const shared_lock&) = delete;
      |                                   ^~~~~~
p1708.cpp:477:46: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  477 | shared_lock& operator=(const shared_lock&) = delete;
      |                                              ^~~~~~
p1708.cpp:478:24: error: expected ',' or '...' before '&&' token
  478 | shared_lock(shared_lock&& u) noexcept;
      |                        ^~
p1708.cpp:478:1: error: invalid constructor; you probably meant 'std::shared_lock<Mutex> (const std::shared_lock<Mutex>&)'
  478 | shared_lock(shared_lock&& u) noexcept;
      | ^~~~~~~~~~~
p1708.cpp:478:28: error: expected ';' at end of member declaration
  478 | shared_lock(shared_lock&& u) noexcept;
      |                            ^
      |                             ;
p1708.cpp:478:30: error: 'noexcept' does not name a type
  478 | shared_lock(shared_lock&& u) noexcept;
      |                              ^~~~~~~~
p1708.cpp:478:30: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:479:35: error: expected ',' or '...' before '&&' token
  479 | shared_lock& operator=(shared_lock&& u) noexcept;
      |                                   ^~
p1708.cpp:479:39: error: expected ';' at end of member declaration
  479 | shared_lock& operator=(shared_lock&& u) noexcept;
      |                                       ^
      |                                        ;
p1708.cpp:479:41: error: 'noexcept' does not name a type
  479 | shared_lock& operator=(shared_lock&& u) noexcept;
      |                                         ^~~~~~~~
p1708.cpp:479:41: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:484:27: error: 'chrono' does not name a type
  484 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                           ^~~~~~
p1708.cpp:484:43: error: expected unqualified-id before '<' token
  484 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                           ^
p1708.cpp:484:43: error: expected ')' before '<' token
  484 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                    ~                      ^
      |                                           )
p1708.cpp:484:43: error: expected initializer before '<' token
p1708.cpp:486:29: error: 'chrono' does not name a type
  486 |   bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                             ^~~~~~
p1708.cpp:486:47: error: expected unqualified-id before '<' token
  486 |   bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                               ^
p1708.cpp:486:47: error: expected ')' before '<' token
  486 |   bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                      ~                        ^
      |                                               )
p1708.cpp:486:47: error: expected initializer before '<' token
p1708.cpp:489:25: error: expected ';' at end of member declaration
  489 | void swap(shared_lock& u) noexcept;
      |                         ^
      |                          ;
p1708.cpp:489:27: error: 'noexcept' does not name a type
  489 | void swap(shared_lock& u) noexcept;
      |                           ^~~~~~~~
p1708.cpp:489:27: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:490:1: error: 'mutex_type' does not name a type
  490 | mutex_type* release() noexcept;
      | ^~~~~~~~~~
p1708.cpp:492:18: error: expected ';' at end of member declaration
  492 | bool owns_lock() const noexcept;
      |                  ^~~~~
      |                       ;
p1708.cpp:492:24: error: 'noexcept' does not name a type
  492 | bool owns_lock() const noexcept;
      |                        ^~~~~~~~
p1708.cpp:492:24: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:493:27: warning: explicit conversion operators only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  493 | explicit operator bool () const noexcept;
      |                           ^~~~~
p1708.cpp:493:27: error: expected ';' at end of member declaration
  493 | explicit operator bool () const noexcept;
      |                           ^~~~~
      |                                ;
p1708.cpp:493:33: error: 'noexcept' does not name a type
  493 | explicit operator bool () const noexcept;
      |                                 ^~~~~~~~
p1708.cpp:493:33: note: C++11 'noexcept' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:494:1: error: 'mutex_type' does not name a type
  494 | mutex_type* mutex() const noexcept;
      | ^~~~~~~~~~
p1708.cpp:496:5: error: 'mutex_type' does not name a type
  496 |     mutex_type* pm;
      |     ^~~~~~~~~~
p1708.cpp:504:10: error: ISO C++ forbids declaration of 'shared_lock' with no type [-fpermissive]
  504 | explicit shared_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:504:1: error: 'explicit' outside class declaration
  504 | explicit shared_lock(mutex_type& m);
      | ^~~~~~~~
p1708.cpp:504:22: error: 'mutex_type' was not declared in this scope
  504 | explicit shared_lock(mutex_type& m);
      |                      ^~~~~~~~~~
p1708.cpp:504:34: error: 'm' was not declared in this scope; did you mean 'tm'?
  504 | explicit shared_lock(mutex_type& m);
      |                                  ^
      |                                  tm
p1708.cpp:506:15: error: expected constructor, destructor, or type conversion before 'noexcept'
  506 | shared_lock() noexcept;
      |               ^~~~~~~~
p1708.cpp:510:12: error: expected constructor, destructor, or type conversion before '(' token
  510 | shared_lock(mutex_type& m, defer_lock_t) noexcept;
      |            ^
p1708.cpp:512:12: error: expected constructor, destructor, or type conversion before '(' token
  512 | shared_lock(mutex_type& m, try_to_lock_t);
      |            ^
p1708.cpp:515:12: error: expected constructor, destructor, or type conversion before '(' token
  515 | shared_lock(mutex_type& m, adopt_lock_t);
      |            ^
p1708.cpp:518:14: error: expected constructor, destructor, or type conversion before '(' token
  518 |   shared_lock(mutex_type& m,
      |              ^
p1708.cpp:523:14: error: expected constructor, destructor, or type conversion before '(' token
  523 |   shared_lock(mutex_type& m,
      |              ^
p1708.cpp:527:13: error: expected class-name before '(' token
  527 | ~shared_lock();
      |             ^
p1708.cpp:529:12: error: expected constructor, destructor, or type conversion before '(' token
  529 | shared_lock(shared_lock&& sl) noexcept;
      |            ^
p1708.cpp:531:1: error: reference to 'shared_lock' is ambiguous
  531 | shared_lock& operator=(shared_lock&& sl) noexcept;
      | ^~~~~~~~~~~
p1708.cpp:467:11: note: candidates are: 'template<class Mutex> class std::shared_lock'
  467 |     class shared_lock {
      |           ^~~~~~~~~~~
p1708.cpp:504:10: note:                 'int shared_lock'
  504 | explicit shared_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:551:29: error: 'chrono' does not name a type
  551 |   bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                             ^~~~~~
p1708.cpp:551:47: error: expected unqualified-id before '<' token
  551 |   bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                                               ^
p1708.cpp:551:47: error: expected ')' before '<' token
  551 |   bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
      |                      ~                        ^
      |                                               )
p1708.cpp:551:47: error: expected initializer before '<' token
p1708.cpp:559:27: error: 'chrono' does not name a type
  559 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                           ^~~~~~
p1708.cpp:559:43: error: expected unqualified-id before '<' token
  559 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                                           ^
p1708.cpp:559:43: error: expected ')' before '<' token
  559 |   bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
      |                    ~                      ^
      |                                           )
p1708.cpp:559:43: error: expected initializer before '<' token
p1708.cpp:572:9: error: variable or field 'swap' declared void
  572 |    void swap(shared_lock& sl) noexcept;
      |         ^~~~
p1708.cpp:572:14: error: reference to 'shared_lock' is ambiguous
  572 |    void swap(shared_lock& sl) noexcept;
      |              ^~~~~~~~~~~
p1708.cpp:467:11: note: candidates are: 'template<class Mutex> class std::shared_lock'
  467 |     class shared_lock {
      |           ^~~~~~~~~~~
p1708.cpp:504:10: note:                 'int shared_lock'
  504 | explicit shared_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:572:27: error: 'sl' was not declared in this scope
  572 |    void swap(shared_lock& sl) noexcept;
      |                           ^~
p1708.cpp:574:1: error: 'mutex_type' does not name a type
  574 | mutex_type* release() noexcept;
      | ^~~~~~~~~~
p1708.cpp:577:8: error: variable or field 'swap' declared void
  577 |   void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |        ^~~~
p1708.cpp:577:13: error: reference to 'shared_lock' is ambiguous
  577 |   void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |             ^~~~~~~~~~~
p1708.cpp:467:11: note: candidates are: 'template<class Mutex> class std::shared_lock'
  467 |     class shared_lock {
      |           ^~~~~~~~~~~
p1708.cpp:504:10: note:                 'int shared_lock'
  504 | explicit shared_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:577:30: error: expected primary-expression before '>' token
  577 |   void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                              ^
p1708.cpp:577:33: error: 'x' was not declared in this scope
  577 |   void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                 ^
p1708.cpp:577:36: error: reference to 'shared_lock' is ambiguous
  577 |   void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                    ^~~~~~~~~~~
p1708.cpp:467:11: note: candidates are: 'template<class Mutex> class std::shared_lock'
  467 |     class shared_lock {
      |           ^~~~~~~~~~~
p1708.cpp:504:10: note:                 'int shared_lock'
  504 | explicit shared_lock(mutex_type& m);
      |          ^~~~~~~~~~~
p1708.cpp:577:53: error: expected primary-expression before '>' token
  577 |   void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                                     ^
p1708.cpp:577:56: error: 'y' was not declared in this scope; did you mean 'yn'?
  577 |   void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                                        ^
      |                                                        yn
p1708.cpp:580:24: error: expected initializer before 'noexcept'
  580 | bool owns_lock() const noexcept;
      |                        ^~~~~~~~
p1708.cpp:582:32: error: expected initializer before 'noexcept'
  582 | explicit operator bool() const noexcept;
      |                                ^~~~~~~~
p1708.cpp:584:1: error: 'mutex_type' does not name a type
  584 | mutex_type* mutex() const noexcept;
      | ^~~~~~~~~~
p1708.cpp:587:35: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  587 | template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
      |                                   ^~~
p1708.cpp:587:69: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  587 | template<class L1, class L2, class... L3> int try_lock(L1&, L2&, L3&...);
      |                                                                     ^~~
p1708.cpp:592:35: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  592 | template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
      |                                   ^~~
p1708.cpp:592:66: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  592 | template<class L1, class L2, class... L3> void lock(L1&, L2&, L3&...);
      |                                                                  ^~~
p1708.cpp:602:7: error: 'constexpr' does not name a type
  602 |       constexpr once_flag() noexcept;
      |       ^~~~~~~~~
p1708.cpp:602:7: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:603:37: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  603 |       once_flag(const once_flag&) = delete;
      |                                     ^~~~~~
p1708.cpp:604:48: warning: defaulted and deleted functions only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  604 |       once_flag& operator=(const once_flag&) = delete;
      |                                                ^~~~~~
p1708.cpp:608:4: error: 'constexpr' does not name a type
  608 |    constexpr once_flag() noexcept;
      |    ^~~~~~~~~
p1708.cpp:608:4: note: C++11 'constexpr' only available with '-std=c++11' or '-std=gnu++11'
p1708.cpp:612:31: warning: variadic templates only available with '-std=c++11' or '-std=gnu++11' [-Wc++11-extensions]
  612 | template<class Callable, class... Args>
      |                               ^~~
p1708.cpp:613:41: error: expected ',' or '...' before '&&' token
  613 | void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |                                         ^~
p1708.cpp:621:21: error: no matching function for call to 'std::once_flag::once_flag()'
  621 |      std::once_flag flag;
      |                     ^~~~
p1708.cpp:603:7: note: candidate: 'std::once_flag::once_flag(const std::once_flag&)' (deleted)
  603 |       once_flag(const once_flag&) = delete;
      |       ^~~~~~~~~
p1708.cpp:603:7: note:   candidate expects 1 argument, 0 provided
p1708.cpp: In function 'void g()':
p1708.cpp:630:30: error: no matching function for call to 'std::once_flag::once_flag()'
  630 |        static std::once_flag flag2;
      |                              ^~~~~
p1708.cpp:603:7: note: candidate: 'std::once_flag::once_flag(const std::once_flag&)' (deleted)
  603 |       once_flag(const once_flag&) = delete;
      |       ^~~~~~~~~
p1708.cpp:603:7: note:   candidate expects 1 argument, 0 provided
p1708.cpp: In member function 'void information::verify()':
p1708.cpp:638:38: error: no matching function for call to 'call_once(std::once_flag&, void (information::*)(), information&)'
  638 |        void verify() { std::call_once(verified, &information::verifier, *this); }
      |                        ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
p1708.cpp:43:10: note: candidate: 'template<class Callable, class ... Args> void std::call_once(once_flag&, Callable)'
   43 |     void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |          ^~~~~~~~~
p1708.cpp:43:10: note:   template argument deduction/substitution failed:
p1708.cpp:638:38: note:   candidate expects 2 arguments, 3 provided
  638 |        void verify() { std::call_once(verified, &information::verifier, *this); }
      |                        ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$ g++ p1708.cpp -std=2b -o p1708g -I. -Wall
p1708.cpp:29:10: error: redefinition of 'struct std::defer_lock_t'
   29 |   struct defer_lock_t { explicit defer_lock_t() = default; };
      |          ^~~~~~~~~~~~
In file included from /usr/local/include/c++/12.1.0/bits/atomic_wait.h:49,
                 from /usr/local/include/c++/12.1.0/bits/atomic_base.h:41,
                 from /usr/local/include/c++/12.1.0/atomic:41,
                 from N4910.h:11,
                 from p1708.cpp:10:
/usr/local/include/c++/12.1.0/bits/std_mutex.h:199:10: note: previous definition of 'struct std::defer_lock_t'
  199 |   struct defer_lock_t { explicit defer_lock_t() = default; };
      |          ^~~~~~~~~~~~
p1708.cpp:30:10: error: redefinition of 'struct std::try_to_lock_t'
   30 |   struct try_to_lock_t { explicit try_to_lock_t() = default; };
      |          ^~~~~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:202:10: note: previous definition of 'struct std::try_to_lock_t'
  202 |   struct try_to_lock_t { explicit try_to_lock_t() = default; };
      |          ^~~~~~~~~~~~~
p1708.cpp:31:10: error: redefinition of 'struct std::adopt_lock_t'
   31 |   struct adopt_lock_t { explicit adopt_lock_t() = default; };
      |          ^~~~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:206:10: note: previous definition of 'struct std::adopt_lock_t'
  206 |   struct adopt_lock_t { explicit adopt_lock_t() = default; };
      |          ^~~~~~~~~~~~
p1708.cpp:32:34: error: redefinition of 'constexpr const std::defer_lock_t std::defer_lock'
   32 |   inline constexpr defer_lock_t  defer_lock { };
      |                                  ^~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:209:49: note: 'constexpr const std::defer_lock_t std::defer_lock' previously defined here
  209 |   _GLIBCXX17_INLINE constexpr defer_lock_t      defer_lock { };
      |                                                 ^~~~~~~~~~
p1708.cpp:33:34: error: redefinition of 'constexpr const std::try_to_lock_t std::try_to_lock'
   33 |   inline constexpr try_to_lock_t try_to_lock { };
      |                                  ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:212:49: note: 'constexpr const std::try_to_lock_t std::try_to_lock' previously defined here
  212 |   _GLIBCXX17_INLINE constexpr try_to_lock_t     try_to_lock { };
      |                                                 ^~~~~~~~~~~
p1708.cpp:34:34: error: redefinition of 'constexpr const std::adopt_lock_t std::adopt_lock'
   34 |   inline constexpr adopt_lock_t  adopt_lock { };
      |                                  ^~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:215:49: note: 'constexpr const std::adopt_lock_t std::adopt_lock' previously defined here
  215 |   _GLIBCXX17_INLINE constexpr adopt_lock_t      adopt_lock { };
      |                                                 ^~~~~~~~~~
p1708.cpp:51:29: error: 'Mutex' was not declared in this scope; did you mean 'mutex'?
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                             ^~~~~
      |                             mutex
p1708.cpp:51:34: error: template argument 1 is invalid
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                  ^
p1708.cpp:51:52: error: 'Mutex' was not declared in this scope; did you mean 'mutex'?
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                                    ^~~~~
      |                                                    mutex
p1708.cpp:51:57: error: template argument 1 is invalid
   51 |       void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
      |                                                         ^
p1708.cpp:89:11: error: redefinition of 'class std::mutex'
   89 |     class mutex {
      |           ^~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:83:9: note: previous definition of 'class std::mutex'
   83 |   class mutex : private __mutex_base
      |         ^~~~~
p1708.cpp:94:21: error: expected constructor, destructor, or type conversion before '=' token
   94 | mutex(const mutex&) = delete;
      |                     ^
p1708.cpp:95:8: error: 'std::mutex& operator=(const std::mutex&)' must be a non-static member function
   95 | mutex& operator=(const mutex&) = delete;
      |        ^~~~~~~~
p1708.cpp:99:28: error: 'implementation' does not name a type
   99 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                            ^~~~~~~~~~~~~~
p1708.cpp:99:52: error: 'native_handle_type' does not name a type
   99 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:116:28: error: 'implementation' does not name a type
  116 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                            ^~~~~~~~~~~~~~
p1708.cpp:116:52: error: 'native_handle_type' does not name a type
  116 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:160:28: error: 'implementation' does not name a type
  160 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                            ^~~~~~~~~~~~~~
p1708.cpp:160:52: error: 'native_handle_type' does not name a type
  160 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:178:28: error: 'implementation' does not name a type
  178 | using native_handle_type = implementation-defined; // see 33.2.3
      |                            ^~~~~~~~~~~~~~
p1708.cpp:179:1: error: 'native_handle_type' does not name a type
  179 | native_handle_type native_handle(); // see 33.2.3
      | ^~~~~~~~~~~~~~~~~~
p1708.cpp:213:11: error: redefinition of 'class std::shared_mutex'
  213 |     class shared_mutex {
      |           ^~~~~~~~~~~~
In file included from p1708.cpp:11:
/usr/local/include/c++/12.1.0/shared_mutex:409:9: note: previous definition of 'class std::shared_mutex'
  409 |   class shared_mutex
      |         ^~~~~~~~~~~~
p1708.cpp:219:16: error: expected constructor, destructor, or type conversion before ';' token
  219 | ~shared_mutex();
      |                ^
p1708.cpp:220:35: error: expected constructor, destructor, or type conversion before '=' token
  220 | shared_mutex(const shared_mutex&) = delete;
      |                                   ^
p1708.cpp:221:15: error: 'std::shared_mutex& operator=(const std::shared_mutex&)' must be a non-static member function
  221 | shared_mutex& operator=(const shared_mutex&) = delete;
      |               ^~~~~~~~
p1708.cpp:232:28: error: 'implementation' does not name a type
  232 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                            ^~~~~~~~~~~~~~
p1708.cpp:232:52: error: 'native_handle_type' does not name a type
  232 | using native_handle_type = implementation-defined; native_handle_type native_handle();
      |                                                    ^~~~~~~~~~~~~~~~~~
p1708.cpp:260:11: error: redefinition of 'class std::shared_timed_mutex'
  260 |     class shared_timed_mutex {
      |           ^~~~~~~~~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:452:9: note: previous definition of 'class std::shared_timed_mutex'
  452 |   class shared_timed_mutex
      |         ^~~~~~~~~~~~~~~~~~
p1708.cpp:294:10: error: redefinition of 'struct std::defer_lock_t'
  294 |   struct defer_lock_t  { };
      |          ^~~~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:199:10: note: previous definition of 'struct std::defer_lock_t'
  199 |   struct defer_lock_t { explicit defer_lock_t() = default; };
      |          ^~~~~~~~~~~~
p1708.cpp:295:10: error: redefinition of 'struct std::try_to_lock_t'
  295 |   struct try_to_lock_t { };
      |          ^~~~~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:202:10: note: previous definition of 'struct std::try_to_lock_t'
  202 |   struct try_to_lock_t { explicit try_to_lock_t() = default; };
      |          ^~~~~~~~~~~~~
p1708.cpp:301:8: error: duplicate 'inline'
  301 |        inline constexpr try_to_lock_t  try_to_lock { };
      |        ^~~~~~
      |        ------
p1708.cpp:301:15: error: duplicate 'constexpr'
  301 |        inline constexpr try_to_lock_t  try_to_lock { };
      |               ^~~~~~~~~
      |               ---------
p1708.cpp:301:40: error: expected initializer before 'try_to_lock'
  301 |        inline constexpr try_to_lock_t  try_to_lock { };
      |                                        ^~~~~~~~~~~
p1708.cpp:302:40: error: redefinition of 'constexpr const std::adopt_lock_t std::adopt_lock'
  302 |        inline constexpr adopt_lock_t   adopt_lock { };
      |                                        ^~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:215:49: note: 'constexpr const std::adopt_lock_t std::adopt_lock' previously defined here
  215 |   _GLIBCXX17_INLINE constexpr adopt_lock_t      adopt_lock { };
      |                                                 ^~~~~~~~~~
p1708.cpp:307:14: error: redefinition of 'class std::lock_guard<_Mutex>'
  307 |        class lock_guard {
      |              ^~~~~~~~~~
/usr/local/include/c++/12.1.0/bits/std_mutex.h:223:11: note: previous definition of 'class std::lock_guard<_Mutex>'
  223 |     class lock_guard
      |           ^~~~~~~~~~
p1708.cpp:318:31: error: expected ')' before '&' token
  318 | explicit lock_guard(mutex_type& m);
      |                    ~          ^
      |                               )
p1708.cpp:319:22: error: expected ')' before '&' token
  319 | lock_guard(mutex_type& m, adopt_lock_t);
      |           ~          ^
      |                      )
p1708.cpp:322:12: error: expected class-name before '(' token
  322 | ~lock_guard();
      |            ^
p1708.cpp:329:20: error: 'see' does not name a type
  329 | using mutex_type = see below ;
      |                    ^~~
p1708.cpp:331:1: error: 'defer_lock' does not name a type; did you mean 'defer_lock_t'?
  331 | defer_lock { };
      | ^~~~~~~~~~
      | defer_lock_t
p1708.cpp:342:32: error: expected ')' before '&' token
  342 | explicit scoped_lock(MutexTypes&... m);
      |                     ~          ^
      |                                )
p1708.cpp:344:34: error: expected ')' before ',' token
  344 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
      |                     ~            ^
      |                                  )
p1708.cpp:344:46: error: expected initializer before '&' token
  344 | explicit scoped_lock(adopt_lock_t, MutexTypes&... m);
      |                                              ^
p1708.cpp:347:13: error: expected class-name before '(' token
  347 | ~scoped_lock();
      |             ^
p1708.cpp:385:4: error: deduction guide for 'std::unique_lock<Mutex>' must have trailing return type
  385 |    unique_lock() noexcept;
      |    ^~~~~~~~~~~
p1708.cpp:36:118: note: 'template<class Mutex> class std::unique_lock' declared here
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:386:32: error: expected ')' before '&' token
  386 | explicit unique_lock(mutex_type& m);
      |                     ~          ^
      |                                )
p1708.cpp:389:23: error: expected ')' before '&' token
  389 | unique_lock(mutex_type& m, defer_lock_t) noexcept;
      |            ~          ^
      |                       )
p1708.cpp:391:23: error: expected ')' before '&' token
  391 | unique_lock(mutex_type& m, try_to_lock_t);
      |            ~          ^
      |                       )
p1708.cpp:394:23: error: expected ')' before '&' token
  394 | unique_lock(mutex_type& m, adopt_lock_t);
      |            ~          ^
      |                       )
p1708.cpp:398:31: error: expected ')' before '&' token
  398 |         unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
      |                    ~          ^
      |                               )
p1708.cpp:402:25: error: expected ')' before '&' token
  402 |   unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
      |              ~          ^
      |                         )
p1708.cpp:405:13: error: template placeholder type 'unique_lock<...auto...>' must be followed by a simple declarator-id
  405 | unique_lock(unique_lock&& u) noexcept;
      |             ^~~~~~~~~~~
p1708.cpp:36:118: note: 'template<class Mutex> class std::unique_lock' declared here
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:405:1: error: deduction guide for 'std::unique_lock<Mutex>' must have trailing return type
  405 | unique_lock(unique_lock&& u) noexcept;
      | ^~~~~~~~~~~
p1708.cpp:36:118: note: 'template<class Mutex> class std::unique_lock' declared here
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:407:24: error: template placeholder type 'unique_lock<...auto...>' must be followed by a simple declarator-id
  407 | unique_lock& operator=(unique_lock&& u);
      |                        ^~~~~~~~~~~
p1708.cpp:36:118: note: 'template<class Mutex> class std::unique_lock' declared here
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:407:1: error: deduced class type 'unique_lock' in function return type
  407 | unique_lock& operator=(unique_lock&& u);
      | ^~~~~~~~~~~
p1708.cpp:36:118: note: 'template<class Mutex> class std::unique_lock' declared here
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:411:13: error: expected class-name before '(' token
  411 | ~unique_lock();
      |             ^
p1708.cpp:448:11: error: template placeholder type 'unique_lock<...auto...>' must be followed by a simple declarator-id
  448 | void swap(unique_lock& u) noexcept;
      |           ^~~~~~~~~~~
p1708.cpp:36:118: note: 'template<class Mutex> class std::unique_lock' declared here
   36 | template<class Mutex> class lock_guard; template<class... MutexTypes> class scoped_lock; template<class Mutex> class unique_lock;
      |                                                                                                                      ^~~~~~~~~~~
p1708.cpp:449:1: error: expected unqualified-id before '[' token
  449 | [thread.lock.unique.mod]
      | ^
p1708.cpp:457:24: error: non-member function 'bool owns_lock()' cannot have cv-qualifier
  457 | bool owns_lock() const noexcept;
      |                        ^~~~~~~~
p1708.cpp:459:1: error: 'explicit' outside class declaration
  459 | explicit operator bool() const noexcept;
      | ^~~~~~~~
p1708.cpp:459:32: error: non-member function 'operator bool()' cannot have cv-qualifier
  459 | explicit operator bool() const noexcept;
      |                                ^~~~~~~~
p1708.cpp:459:10: error: 'operator bool()' must be a non-static member function
  459 | explicit operator bool() const noexcept;
      |          ^~~~~~~~
p1708.cpp:461:1: error: 'mutex_type' does not name a type
  461 | mutex_type *mutex() const noexcept;
      | ^~~~~~~~~~
p1708.cpp:467:11: error: redefinition of 'class std::shared_lock<_Mutex>'
  467 |     class shared_lock {
      |           ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:715:11: note: previous definition of 'class std::shared_lock<_Mutex>'
  715 |     class shared_lock
      |           ^~~~~~~~~~~
p1708.cpp:504:32: error: expected ')' before '&' token
  504 | explicit shared_lock(mutex_type& m);
      |                     ~          ^
      |                                )
p1708.cpp:506:1: error: deduction guide for 'std::shared_lock<_Mutex>' must have trailing return type
  506 | shared_lock() noexcept;
      | ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:715:11: note: 'template<class _Mutex> class std::shared_lock' declared here
  715 |     class shared_lock
      |           ^~~~~~~~~~~
p1708.cpp:510:23: error: expected ')' before '&' token
  510 | shared_lock(mutex_type& m, defer_lock_t) noexcept;
      |            ~          ^
      |                       )
p1708.cpp:512:23: error: expected ')' before '&' token
  512 | shared_lock(mutex_type& m, try_to_lock_t);
      |            ~          ^
      |                       )
p1708.cpp:515:23: error: expected ')' before '&' token
  515 | shared_lock(mutex_type& m, adopt_lock_t);
      |            ~          ^
      |                       )
p1708.cpp:518:25: error: expected ')' before '&' token
  518 |   shared_lock(mutex_type& m,
      |              ~          ^
      |                         )
p1708.cpp:523:25: error: expected ')' before '&' token
  523 |   shared_lock(mutex_type& m,
      |              ~          ^
      |                         )
p1708.cpp:527:13: error: expected class-name before '(' token
  527 | ~shared_lock();
      |             ^
p1708.cpp:529:13: error: template placeholder type 'shared_lock<...auto...>' must be followed by a simple declarator-id
  529 | shared_lock(shared_lock&& sl) noexcept;
      |             ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:715:11: note: 'template<class _Mutex> class std::shared_lock' declared here
  715 |     class shared_lock
      |           ^~~~~~~~~~~
p1708.cpp:529:1: error: deduction guide for 'std::shared_lock<_Mutex>' must have trailing return type
  529 | shared_lock(shared_lock&& sl) noexcept;
      | ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:715:11: note: 'template<class _Mutex> class std::shared_lock' declared here
  715 |     class shared_lock
      |           ^~~~~~~~~~~
p1708.cpp:531:24: error: template placeholder type 'shared_lock<...auto...>' must be followed by a simple declarator-id
  531 | shared_lock& operator=(shared_lock&& sl) noexcept;
      |                        ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:715:11: note: 'template<class _Mutex> class std::shared_lock' declared here
  715 |     class shared_lock
      |           ^~~~~~~~~~~
p1708.cpp:531:1: error: deduced class type 'shared_lock' in function return type
  531 | shared_lock& operator=(shared_lock&& sl) noexcept;
      | ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:715:11: note: 'template<class _Mutex> class std::shared_lock' declared here
  715 |     class shared_lock
      |           ^~~~~~~~~~~
p1708.cpp:572:14: error: template placeholder type 'shared_lock<...auto...>' must be followed by a simple declarator-id
  572 |    void swap(shared_lock& sl) noexcept;
      |              ^~~~~~~~~~~
/usr/local/include/c++/12.1.0/shared_mutex:715:11: note: 'template<class _Mutex> class std::shared_lock' declared here
  715 |     class shared_lock
      |           ^~~~~~~~~~~
p1708.cpp:574:1: error: 'mutex_type' does not name a type
  574 | mutex_type* release() noexcept;
      | ^~~~~~~~~~
p1708.cpp:580:24: error: non-member function 'bool owns_lock()' cannot have cv-qualifier
  580 | bool owns_lock() const noexcept;
      |                        ^~~~~~~~
p1708.cpp:582:1: error: 'explicit' outside class declaration
  582 | explicit operator bool() const noexcept;
      | ^~~~~~~~
p1708.cpp:582:32: error: non-member function 'operator bool()' cannot have cv-qualifier
  582 | explicit operator bool() const noexcept;
      |                                ^~~~~~~~
p1708.cpp:582:10: error: 'operator bool()' must be a non-static member function
  582 | explicit operator bool() const noexcept;
      |          ^~~~~~~~
p1708.cpp:584:1: error: 'mutex_type' does not name a type
  584 | mutex_type* mutex() const noexcept;
      | ^~~~~~~~~~
p1708.cpp:608:14: error: ISO C++ forbids declaration of 'once_flag' with no type [-fpermissive]
  608 |    constexpr once_flag() noexcept;
      |              ^~~~~~~~~
p1708.cpp:613:6: error: variable or field 'call_once' declared void
  613 | void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |      ^~~~~~~~~
p1708.cpp:613:16: error: reference to 'once_flag' is ambiguous
  613 | void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |                ^~~~~~~~~
p1708.cpp:601:12: note: candidates are: 'struct std::once_flag'
  601 |     struct once_flag {
      |            ^~~~~~~~~
p1708.cpp:608:14: note:                 'constexpr int once_flag()'
  608 |    constexpr once_flag() noexcept;
      |              ^~~~~~~~~
p1708.cpp:613:27: error: 'flag' was not declared in this scope
  613 | void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |                           ^~~~
p1708.cpp:613:41: error: expected primary-expression before '&&' token
  613 | void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |                                         ^~
p1708.cpp:613:44: error: 'func' was not declared in this scope
  613 | void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |                                            ^~~~
p1708.cpp:613:54: error: expected primary-expression before '&&' token
  613 | void call_once(once_flag& flag, Callable&& func, Args&&... args);
      |                                                      ^~
p1708.cpp:602:17: warning: inline function 'constexpr std::once_flag::once_flag()' used but never defined
  602 |       constexpr once_flag() noexcept;
      |                 ^~~~~~~~~

検討事項(agenda)

コンパイルエラーを取るか、コンパイルエラーの理由を解説する。

応用例1 AUTOSAR C++

AUTOSARでC++のコーディング標準を作っている。 
MISRA-C++コーディング標準の改訂をまたずに、C++14に対応したかったためかもしれない。 

Autosar Guidelines C++14 example code compile list

MISRA C++, AUTOSAR C++について

応用例2 MISRA C/C++

MISRA C まとめ #include

MISRA C++ 5-0-16

応用例3 CERT C/C++

SEI CERT C++ Coding Standard AA. Bibliography 確認中。

MISRA C/C++, AUTOSAR C++, CERT C/C++とC/C++工業標準をコンパイルする

応用例4 箱庭 

箱庭もくもく会

第11回 未定

箱庭ではUnityをはじめC++を使っているらしい。 

ここでコンパイルしたコードと同じようなコードを使っているか、
ここで出たコンパイルエラーと同じようなエラーがでたかを
いろいろな版のコンパイラでコンパイルして確認していく。

この項目は、箱庭プロジェクトを市場分析の対象として、原則的には、箱庭プロジェクトの外部から分析し、外部から箱庭の広告宣伝のための戦略会議を仮想した結果、仮想「箱庭もくもく会」を開催してみることを企画するものである。 
一切の内容は、箱庭プロジェクト、Athrill, TOPPERSとは無関係である。 
一(いち)参加データアナリストの、個人的なつぶやきです。

仮想戦略会議「箱庭」

お盆には「箱庭」記事を書きましょう「もくもく会」の題材になる(1)

お盆には「箱庭」記事を書きましょう「もくもく会」の題材になる(2)

自己参考資料(self reference)

関連する自己参照以外は、こちらの先頭に移転。

C言語(C++)に対する誤解、曲解、無理解、爽快。

#include "N4910.h"

C++N4910資料の改善点

dockerにclang

docker gnu(gcc/g++) and llvm(clang/clang++)

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)

C++N4910:2022 tag follower 300人超えました。ありがとうございます。

astyle 使ってみた

<この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。>

文書履歴(document history)

ver. 0.01 初稿  20220925

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0