On Mon, 25 May 2026 at 11:20, Aryan Naraghi via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hi everyone,

std::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/