This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.

3161. Container adapters mandate use of emplace_back but don't require it

Section: 23.6.6 [stack], 23.6.3 [queue] Status: NAD Submitter: Marshall Clow Opened: 2018-10-02 Last modified: 2026-06-10

Priority: 3

View all other issues in [stack].

View all issues with NAD status.

Discussion:

23.6.6 [stack] p1 says:

Any sequence container supporting operations back(), push_back() and pop_back() can be used to instantiate stack.

but then in 23.6.6.2 [stack.defn] we have the following code:

template<class... Args>
  decltype(auto) emplace(Args&&... args)
    { return c.emplace_back(std::forward<Args>(args)...); }

The same pattern appears in 23.6.3 [queue].

I see two ways to resolve this:

The first is to add emplace_back() to the list of requirements for underlying containers for stack and queue

The second is to replace the calls to c.emplace_back(std::forward<Args>(args)...) with c.emplace(c.end(), std::forward<Args>(args)...). We can do this w/o messing with the list above because emplace is part of the sequence container requirements, while emplace_back is not. I checked the libc++ implementation of vector, deque, and list, and they all do the same thing for emplace(end(), ...) and emplace_back(...).

[2019-02; Kona Wednesday night issue processing]

Status to Open; Casey to provide updated wording, and re-vote on reflector.

Polls were: NAD - 5-1-3; "Option B" - 2-5-2 and "Probe the container" - 7-2-0

Previous resolution [SUPERSEDED]

This wording is relative to N4762.

I have prepared two mutually exclusive options.
Option A a requirement for emplace_back to the underlying container.
Option B one replaces the calls to emplace_back with calls to emplace.

Option A

  1. Edit 23.6.6 [stack], as indicated:

    Any sequence container supporting operations back(), push_back(), emplace_back() and pop_back() can be used to instantiate stack.

  2. Edit 23.6.3.1 [queue.defn], as indicated:

    Any sequence container supporting operations front(), back(), push_back(), emplace_back() and pop_front() can be used to instantiate queue.

Option B

  1. Edit 23.6.6.2 [stack.defn], class template stack definition, as indicated:

    template<class... Args>
      decltype(auto) emplace(Args&&... args)
        { return c.emplace_back(c.end(), std::forward<Args>(args)...); }
    
  2. Edit 23.6.3.1 [queue.defn], class template queue definition, as indicated:

    template<class... Args>
      decltype(auto) emplace(Args&&... args)
        { return c.emplace_back(c.end(), std::forward<Args>(args)...); }
    

[2020-05 Casey provides new wording]

This is the "probe for emplace_back with fallback to emplace" approach that LWG wanted to see wording for in Kona.

[2020-05-09; Reflector prioritization]

Set priority to 3 after reflector discussions.

[Brno 2026-06-10; Status changed: Open → NAD.]

No need to add it to the class-wide requirements, because emplace_back isn't needed unless you actually call this emplace function. We can't add a requires-clause or Constraints: element because that would only tell you whether the underlying container has an emplace_back member, not whether calling it would actually work for a given set of arguments (because none of the standard sequence containers constraint their emplace_back members). We don't feel any change is needed, it works for vector and deque and if it doesn't work for some other underlying container, don't call it.

Proposed resolution:

This wording is relative to N4861.

  1. Edit 23.6.6.2 [stack.defn], class template stack definition, as indicated:

    template<class... Args>
      decltype(auto) emplace(Args&&... args) {
        if constexpr (requires { c.emplace_back(std::forward<Args>(args)...); }) {
          return c.emplace_back(std::forward<Args>(args)...);
        } else {
          return c.emplace(c.end(), std::forward<Args>(args)...);
        }
      }
    
  2. Edit 23.6.3.1 [queue.defn], class template queue definition, as indicated:

    template<class... Args>
      decltype(auto) emplace(Args&&... args) {
        if constexpr (requires { c.emplace_back(std::forward<Args>(args)...); }) {
          return c.emplace_back(std::forward<Args>(args)...);
        } else {
          return c.emplace(c.end(), std::forward<Args>(args)...);
        }
      }