Open In App

C++ 23 – <flat_map> Header

Last Updated : 22 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

C++23 introduces a new header, <flat_map>, which revolutionizes the manner we store and retrieve key-value pairs. Traditionally, C++ developers have depended on map and unordered_map containers for associative storage. However, the flat_map container gives a singular technique by combining the advantages of each ordered and contiguous storage. In this article, we will explore the <flat_map> header, syntax, and its advantages through examples and use cases.

std::flat_map

The std::flat_map is a class template of flat_map container that provides an efficient data structure for storing key-value pairs.

  • flat_map has the combined functionality of a map and vector.
  • flat_map ensures that values are stored in sorted order primarily based on the keys, and also maintains the elements in a contiguous memory layout. This combination allows for fast access, random access, and faster traversal than its counterparts.
  • To use flat_map, we include the <flat_map> header in C++23 and declare an instance of the container with the desired key and value types.

Syntax of std::flat_map

flat_map < keyType, valueType > name;

std::flat_map Initialization

We can initialize a flat_map container in C++ using the following methods:

1. Using the Initializer List

We can initialize std::flat_map by proving key and value pairs in the initializer list.

Example

flat_set <int, string> object_name { {3, "three"}, {1, "one"}, {4, "four"} };

2. Using the Range Constructor

We can use the range constructor to initialize the std::flat_map object with key and value pairs by specifying the range using the starting iterator and ending iterator.

Example

flat_map <keyType, valueType > object_name(startingIterator, endingIterator);

3. Using the Assignment Operator

We can simply initialize the flat_map object object with another already existing flat_map object using an assignment operator.

Example

flat_set <keyType, valueType > object_name;
object_name = prev_object;

4. Using the Move Assignment Operator

We can initialize a std::flat_map using the move assignment operator. This way of initializing a std::flat_map is memory efficient because the assigned object simply points to the existing memory location where the data is stored without creating unnecessary copies of data.

Example

flat_set <keyType, valueType > object_name;
object_name = move(prev_object);

Example of std::flat_map

C++




// C++ program to illustrate the flat_map header
#include <flat_map>
#include <iostream>
using namespace std;
  
int main()
{
    // Create an instance of flat_map with int keys and
    // string values using an initializer list
    flat_map<int, string> myFlatMap
        = { { 1, "Geeks" }, { 3, "for" }, { 2, "Geeks" } };
  
    for (const auto& pair : myFlatMap) {
        // Iterate over each key-value pair in the flat_map
        // and print the key and value
        cout << "Key: " << pair.first
             << ", Value: " << pair.second << endl;
    }
  
    return 0;
}


Output

Key: 1, Value: Geeks
Key: 2, Value: Geeks
Key: 3, Value: for

Commonly Used Methods

The following are some member functions for basic operation on the flat_map container:

1. Iterators

Iterators are used to traverse the container. The following function returns iterators to the flat_map containers:

  • begin() – Returns an iterator pointing to the first element in the flat_map.
  • end() – Returns an iterator pointing to the position just after the last element in the flat_map.

Example

C++




// C++ program to traverse the flat_map using begin() and
// end()
#include <flat_map>
#include <iostream>
using namespace std;
  
int main()
{
    flat_map<int, string> myMap = { { 1, "Geeks" },
                                    { 2, "for" },
                                    { 3, "Geeks" },
                                    { 4, "Coding" } };
  
    // Iterate over the map using begin() and end()
    cout << "All key-value pairs in the map:" << endl;
    for (auto it = myMap.begin(); it != myMap.end(); ++it) {
        cout << "Key: " << it->first
             << ", Value: " << it->second << endl;
    }
  
    return 0;
}


Output

All key-value pairs in the map:
Key: 1, Value: Geeks
Key: 2, Value: for
Key: 3, Value: Geeks
Key: 4, Value: Coding

2. Modifiers

  • pair insert(keyvalue, mapvalue): Adds a new element to the map.
  • erase(iterator position): Removes the element at the position pointed by the iterator.
  • erase(const key_type& g): Removes the key value ‘g’ from the map.
  • clear() – Removes all the elements from the map.

Example

C++




// C++ program to demonstrate the usage of
// pair insert(), erase(key), erase(position)
// clear() functions
  
#include <flat_map>
#include <iostream>
using namespace std;
  
int main()
{
    flat_map<int, string> myMap;
  
    // Insert key-value pairs using insert()
    myMap.insert(make_pair(1, "Geeks"));
    myMap.insert(make_pair(2, "for"));
    myMap.insert(make_pair(3, "Geeks"));
    myMap.insert(make_pair(4, "Coding"));
  
    // Print the map before erasing
    cout << "Map before erasing:" << endl;
    for (const auto& pair : myMap) {
        cout << "Key: " << pair.first
             << ", Value: " << pair.second << endl;
    }
  
    // Erase an element by key using erase()
    myMap.erase(3);
  
    // Print the map after erasing by key
    cout << "Map after erasing by key:" << endl;
    for (const auto& pair : myMap) {
        cout << "Key: " << pair.first
             << ", Value: " << pair.second << endl;
    }
  
    // Clear the map using clear()
    myMap.clear();
  
    // Check if the map is empty after clearing
    if (myMap.empty()) {
        cout << "The map is empty after clearing." << endl;
    }
  
    return 0;
}


Output

Map before erasing:
Key: 1, Value: Geeks
Key: 2, Value: for
Key: 3, Value: Geeks
Key: 4, Value: Coding
Map after erasing by key:
Key: 1, Value: Geeks
Key: 2, Value: for
Key: 4, Value: Coding
The map is empty after clearing.

3. Size

  • size() – Returns the number of elements in the flat_map.
  • max_size() – Returns the maximum number of elements that the flat_map can hold.
  • empty() – Returns whether the flat_map is empty.

Example

C++




// C++ program to demonstrate the usage of
// size(), max_size() and empty() functions
#include <flat_map>
#include <iostream>
using namespace std;
  
int main()
{
    flat_map<int, string> myMap
        = { { 1, "Geeks" }, { 2, "for" }, { 3, "Geeks" } };
  
    // Get the size of the map using size()
    cout << "Size of the map: " << myMap.size() << endl;
  
    // Get the maximum possible size of the map using
    // max_size()
    cout << "Maximum possible size of the map: "
         << myMap.max_size() << endl;
  
    // Check if the map is empty using empty()
    if (myMap.empty()) {
        cout << "The map is empty." << endl;
    }
    else {
        cout << "The map is not empty." << endl;
    }
  
    return 0;
}


Output

Size of the map: 3
Maximum possible size of the map: 256204778801521550
The map is not empty.

4. Map operations

  • bool contains(const key_type& g) const – Returns true if there is an element present with key value ‘g’ in the flat_map, else it returns false.
  • find(const key_type & g) – Returns an iterator pointing to an element with the key value ‘g’, or end() if such an element is not present in the flat_map.
  • count(const key_type & g) const – Returns the number of elements with key value ‘g’.

Example

C++




// C++ program to demonstrate the usage of
// contains(), find() and count() functions
  
#include <flat_map>
#include <iostream>
  
int main()
{
    flat_map<int, string> myMap;
  
    myMap.insert(make_pair(1, "Geeks"));
    myMap.insert(make_pair(2, "for"));
    myMap.insert(make_pair(3, "Geeks"));
  
    // Check if a key exists using contains()
    if (myMap.contains(2)) {
        cout << "Key 2 exists in the map." << endl;
    }
  
    // Find an element by key using find()
    auto it = myMap.find(3);
    if (it != myMap.end()) {
        cout << "Value at key 3: " << it->second << endl;
    }
  
    // Count the number of elements with a specific key
    // using count()
    int key = 2;
    int numOccurrences = myMap.count(key);
    cout << "Number of occurrences of key " << key << ": "
         << numOccurrences << endl;
  
    return 0;
}


Output

Key 2 exists in the map.
Value at key 3: Geeks
Number of occurrences of key 2: 1

Advantages of flat_map

  • One of the key benefits of flat_map is its ability to provide fast search, insertion, and deletion operations while maintaining the sorted order.
  • It offers logarithmic time complexity for these operations, making it appropriate for programs that require efficient key-value storage and retrieval.
  • The contiguous memory format of flat_map allows for cache-friendly access patterns, in addition to improving performance.

Applications of flat_map

flat_map finds its utility in a wide range of situations. For example, consider a dictionary application where words are stored as keys, and their definitions are stored as values. By the usage of <flat_map>, we will quickly look for a phrase’s definition based on its key.

Another use case is in leaderboard management, where the scores act as keys and participant names act as values. With flat_map, we can efficiently retrieve the top scores or perform operations like updating scores or removing off players.

Conclusion

C++23’s flat_map header offers a powerful and efficient solution for key-value storage and retrieval. By combining the benefits of ordered and contiguous storage, flat_map gives fast and sorted access to elements.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads