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

### 1197. Can unordered containers have `bucket_count() == 0`?

Section: 22.2.7 [unord.req] Status: C++11 Submitter: Howard Hinnant Opened: 2009-08-24 Last modified: 2016-01-28

Priority: Not Prioritized

View other active issues in [unord.req].

View all other issues in [unord.req].

View all issues with C++11 status.

Discussion:

Table 97 "Unordered associative container requirements" in 22.2.7 [unord.req] says:

> Table 97 — Unordered associative container requirements (in addition to container)
> Expression | Return type | Assertion/note pre-/post-condition | Complexity
> --- | --- | --- | ---
> `b.bucket(k)` | `size_type` | Returns the index of the bucket in which elements with keys equivalent to `k` would be found, if any such element existed. Post: the return value shall be in the range `[0, b.bucket_count())`. | Constant

What should `b.bucket(k)` return if `b.bucket_count() == 0`?

I believe allowing `b.bucket_count() == 0` is important. It is a very reasonable post-condition of the default constructor, or of a moved-from container.

I can think of several reasonable results from `b.bucket(k)` when `b.bucket_count() == 0`:

1. Return 0.
2. Return `numeric_limits<size_type>::max()`.
3. Throw a `domain_error`.
4. Requires: `b.bucket_count() != 0`.

[ 2009-08-26 Daniel adds: ]

> A forth choice would be to add the pre-condition "`b.bucket_count() != 0`" and thus imply undefined behavior if this is violated.

> [ Howard: I like this option too, added to the list. ]

> Further on here my own favorite solution (rationale see below):

> Suggested resolution:

> [Rationale: I suggest to follow choice (1). The main reason is that all associative container functions which take a key argument, are basically free of pre-conditions and non-disrupting, therefore excluding choices (3) and (4). Option (2) seems a bit unexpected to me. It would be more natural, if several similar functions would exist which would also justify the existence of a symbolic constant like npos for this situation. The value 0 is both simple and consistent, it has exactly the same role as a past-the-end iterator value. A typical use-case is:

> >     size_type pos = m.bucket(key);
> >     if (pos != m.bucket_count()) {
> >      ...
> >     } else {
> >      ...
> >     }

> — end Rationale]

> - Change Table 97 in 22.2.7 [unord.req] as follows (Row b.bucket(k), Column "Assertion/..."):

> > Table 97 — Unordered associative container requirements (in addition to container)
> > Expression | Return type | Assertion/note pre-/post-condition | Complexity
> > --- | --- | --- | ---
> > `b.bucket(k)` | `size_type` | Returns the index of the bucket in which elements with keys equivalent to `k` would be found, if any such element existed. Post: if b.bucket_count() != 0, the return value shall be in the range `[0, b.bucket_count())`, otherwise 0. | Constant

[ 2010-01-25 Choice 4 put into proposed resolution section. ]

[ 2010-01-31 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]

Proposed resolution:

Change Table 97 in 22.2.7 [unord.req] as follows (Row b.bucket(k), Column "Assertion/..."):

> Table 97 — Unordered associative container requirements (in addition to container)
> Expression | Return type | Assertion/note pre-/post-condition | Complexity
> --- | --- | --- | ---
> `b.bucket(k)` | `size_type` | Pre: `b.bucket_count() > 0` Returns the index of the bucket in which elements with keys equivalent to `k` would be found, if any such element existed. Post: the return value shall be in the range `[0, b.bucket_count())`. | Constant