coding challenges · advanced
Generic Key-Value Store — any vs variant
Microsoft generic key-value store (string key, any-type value). Store heterogeneous types with std::any (unbounded types, type-erased, RTTI, may heap-allocate) or std::variant<...> (a known closed set — no RTTI, inline, visitable). The crux is safe retrieval: use the pointer form any_cast<T>(&value) (or std::get_if<T> for variant), which returns nullptr on a type mismatch, and wrap the result in std::optional<T> so a missing key or wrong type yields an empty optional instead of throwing bad_any_cast. For concurrency use a std::shared_mutex: get takes a shared_lock (many readers), put/erase take a unique_lock (one writer); mark it mutable and return values by COPY so a concurrent erase can't dangle a reference. O(1) average put/get. Scale follow-ups: shard the map with striped locks, add TTL/LRU eviction, and serialize via std::visit. Prefer variant when the value types are known, any when callers store arbitrary types.
Generic KV store: string→std::any (any type, runtime-checked) or string→std::variant<...> (closed set, compile-time, visitable). Safe get<T> uses the POINTER form any_cast<T>(&v)/get_if<T> → optional<T> (no throw on wrong type). Thread-safety: shared_mutex (shared_lock readers, unique_lock writers); return by value to avoid dangling. O(1) avg; scale via sharded locks + TTL/LRU eviction.
The code
// Generic in-memory KV store: string key, value of ANY type.// Option A — std::any (type-erased, runtime-checked).class Store { std::unordered_map<std::string, std::any> m_; mutable std::shared_mutex mtx_;public: template<class T> void put(const std::string& k, T v) { std::unique_lock lk(mtx_); // writer: exclusive m_[k] = std::move(v); } template<class T> std::optional<T> get(const std::string& k) const { std::shared_lock lk(mtx_); // readers: shared auto it = m_.find(k); if (it == m_.end()) return std::nullopt; if (auto* p = std::any_cast<T>(&it->second)) return *p; // type match? return std::nullopt; // wrong T -> empty, no throw } bool erase(const std::string& k) { std::unique_lock lk(mtx_); return m_.erase(k) > 0; }};
// Option B — std::variant<int,double,std::string,...> when the value set// is a KNOWN, closed list of types (visitable, no RTTI, smaller).What this lesson walks through
- 01One map, values of any type
- 02Safe get — pointer-cast into optional<T>
- 03Thread-safe with a readers/writer lock
- 04variant when the type set is closed
- 05What the question really tests
Key is a string, value can be any type. Two clean ways to hold heterogeneous types in one map: std::any (unbounded set, checked at runtime) or std::variant<…> (a known closed set, checked at compile time and visitable).
See it animated — step by step, at your own pace
Unlock the full interactive walkthrough of Generic Key-Value Store — any vs variant and 100+ animated C++ interview lessons.