2731. Existence of lock_guard<MutexTypes...>::mutex_type typedef unclear

Section: 32.6.5.2 [thread.lock.guard] Status: C++23 Submitter: Eric Fiselier Opened: 2016-06-13 Last modified: 2023-11-22

Priority: 3

View all other issues in [thread.lock.guard].

View all issues with C++23 status.

Discussion:

In the synopsis of 32.6.5.3 [thread.lock.scoped] the mutex_type typedef is specified as follows:

template <class... MutexTypes>
class scoped_lock {
public:
  typedef Mutex mutex_type; // If MutexTypes... consists of the single type Mutex
  […]
};

The comment seems ambiguous as it could mean either:

  1. sizeof...(MutexTypes) == 1.
  2. sizeof...(MutexTypes) >= 1 and every type in MutexTypes... is the same type.

I originally took the language to mean (2), but upon further review it seems that (1) is the intended interpretation, as suggested in the LEWG discussion in Lenexa.

I think the language should be clarified to prevent implementation divergence.

[2016-07, Toronto Saturday afternoon issues processing]

General feeling that sizeof(MutexTypes...) == 1 is a better way to state the requirement.

Reworked the text to refer to scoped_lock instead of lock_guard

Marshall and Eric to reword and discuss on reflector. Status to Open

[2018-3-14 Wednesday evening issues processing; general agreement to adopt once the wording is updated.]

2018-03-18 Marshall provides updated wording.

Previous resolution: [SUPERSEDED]

This wording is relative to N4594.

  1. Edit 32.6.5.2 [thread.lock.guard]/1, class template lock_guard synopsis, as indicated:

    template <class... MutexTypes>
    class lock_guard {
    public:
      typedef Mutex mutex_type; // Only iIf MutexTypes... consists of theexpands to a single type Mutex
      […]
    };
    
Previous resolution: [SUPERSEDED]

This wording is relative to N4727.

  1. Edit 32.6.5.2 [thread.lock.guard]/1, class template lock_guard synopsis, as indicated:

    template <class... MutexTypes>
    class scoped_lock {
    public:
      using mutex_type = Mutex; // Only iIf sizeof(MutexTypes...) == 1 MutexTypes... consists of the single type Mutex
      […]
    };
    

[2020-05-11; Daniel provides improved wording]

[2020-05-16 Reflector discussions]

Status to Tentatively Ready after five positive votes on the reflector.

[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative to N4861.

  1. Edit 32.6.5.3 [thread.lock.scoped], class template scoped_lock synopsis, as indicated:

    template <class... MutexTypes>
    class scoped_lock {
    public:
      using mutex_type = Mutex; // If MutexTypes... consists of the single type Mutex
      using mutex_type = see below; // Only if  sizeof...(MutexTypes) == 1
      […]
    };
    

    -1- 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 [basic.life]). 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.

    • WhenIf sizeof...(MutexTypes) is 1one, let Mutex denote the sole type constituting the pack MutexTypes., the supplied Mutex type shall meet the Cpp17BasicLockable requirements (32.2.5.2 [thread.req.lockable.basic]). The member typedef-name mutex_type denotes the same type as Mutex.

    • Otherwise, each of the mutex typesall types in the template parameter pack MutexTypes shall meet the Cpp17Lockable requirements (32.2.5.3 [thread.req.lockable.req]) and there is no member mutex_type.