Date: Mon, 25 May 2026 22:44:09 +0800
On Mon, 25 May 2026 at 11:20, Aryan Naraghi via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Hi everyone,
>
> std::flat_map' <https://en.cppreference.com/cpp/container/flat_map>s
> KeyContainer and MappedContainer default to std::vector<Key> and
> std::vector<T>, respectively. Because both KeyContainer and MappedContainer
> must be sequence containers, it is illegal to create a flat_map with Key =
> bool or T = bool. Example:
>
> // -stdlib=libstdc++: compiles
> // -stdlib=libc++: fails with static assertion ("vector<bool> is not a
> sequence container")
> std::flat_map<int, bool> my_map;
>
> // -stdlib=libstdc++: now fails to compile (can't return bool&)
> my_map[1] = true;
>
> To get std::flat_map<int, bool> working, the user must override
> MappedContainer with a sequence container. Example:
>
> std::flat_map<int, bool, std::less<int>, std::vector<int>,
> std::deque<bool>> my_map; // Ok
>
> This is verbose for a fairly common use case and unapproachable for new
> C++ developers. Some of the generated errors are quite hard for a beginner
> to understand (even with libc++'s static assertion).
>
> Is there anything in flight to address this? If not, is this worth
> pursuing?
>
> One approach would be to change the std::flat_map definition from:
>
> template<
> class Key,
> class T,
> class Compare = std::less<Key>,
> class KeyContainer = std::vector<Key>,
> class MappedContainer = std::vector<T>
> > class flat_map;
>
> To:
>
> // Note exposition-only helper.
> template <class T>
> using /*default-flat-map-container*/ = std::conditional_t<
> std::is_same_v<T, bool>,
> std::deque<bool>,
> std::vector<T>>;
>
> template<
> class Key,
> class T,
> class Compare = std::less<Key>,
> class KeyContainer = /*default-flat-map-container*/<Key>,
> class MappedContainer = /*default-flat-map-container*/<T>
> > class flat_map;
>
I like this approach in general.
When I implemented a flat_map for a project using C++17, I used another
trick, but it was also on MappedContainer. I made like it:
template<
class Key,
class T,
class Compare = std::less<Key>,
class KeyContainer = std::vector<Key>,
class MappedContainer = std::vector<ValueProxy_t<T>>
> class flat_map;
ValueProxy_t<T> is BoolObj for bool, T otherwise. BoolObj behaved like bool
but occupied a full byte.
It satisfied my needs, though maybe a bit tricky. Practically speaking, it
is unlikely people will use bool as a key for flat_map, but I think your
approach is OK overall.
std-proposals_at_[hidden]> wrote:
> Hi everyone,
>
> std::flat_map' <https://en.cppreference.com/cpp/container/flat_map>s
> KeyContainer and MappedContainer default to std::vector<Key> and
> std::vector<T>, respectively. Because both KeyContainer and MappedContainer
> must be sequence containers, it is illegal to create a flat_map with Key =
> bool or T = bool. Example:
>
> // -stdlib=libstdc++: compiles
> // -stdlib=libc++: fails with static assertion ("vector<bool> is not a
> sequence container")
> std::flat_map<int, bool> my_map;
>
> // -stdlib=libstdc++: now fails to compile (can't return bool&)
> my_map[1] = true;
>
> To get std::flat_map<int, bool> working, the user must override
> MappedContainer with a sequence container. Example:
>
> std::flat_map<int, bool, std::less<int>, std::vector<int>,
> std::deque<bool>> my_map; // Ok
>
> This is verbose for a fairly common use case and unapproachable for new
> C++ developers. Some of the generated errors are quite hard for a beginner
> to understand (even with libc++'s static assertion).
>
> Is there anything in flight to address this? If not, is this worth
> pursuing?
>
> One approach would be to change the std::flat_map definition from:
>
> template<
> class Key,
> class T,
> class Compare = std::less<Key>,
> class KeyContainer = std::vector<Key>,
> class MappedContainer = std::vector<T>
> > class flat_map;
>
> To:
>
> // Note exposition-only helper.
> template <class T>
> using /*default-flat-map-container*/ = std::conditional_t<
> std::is_same_v<T, bool>,
> std::deque<bool>,
> std::vector<T>>;
>
> template<
> class Key,
> class T,
> class Compare = std::less<Key>,
> class KeyContainer = /*default-flat-map-container*/<Key>,
> class MappedContainer = /*default-flat-map-container*/<T>
> > class flat_map;
>
I like this approach in general.
When I implemented a flat_map for a project using C++17, I used another
trick, but it was also on MappedContainer. I made like it:
template<
class Key,
class T,
class Compare = std::less<Key>,
class KeyContainer = std::vector<Key>,
class MappedContainer = std::vector<ValueProxy_t<T>>
> class flat_map;
ValueProxy_t<T> is BoolObj for bool, T otherwise. BoolObj behaved like bool
but occupied a full byte.
It satisfied my needs, though maybe a bit tricky. Practically speaking, it
is unlikely people will use bool as a key for flat_map, but I think your
approach is OK overall.
-- Yongwei Wu URL: http://wyw.dcweb.cn/
Received on 2026-05-25 14:44:26
