Что-то простое и немного странное:
#include <map>
#include <string>
#include <optional>
struct rmap : std::map<std::string, rmap>
{
std::optional<std::string> value; // could be anything (std::variant, std::any, ...)
};
С небольшим количеством сахара и некоторыми другими вкусными настройками вы можете использовать его так, как намереваетесь:
#include <map>
#include <string>
#include <optional>
#include <iostream>
struct rmap : std::map<std::string, rmap>
{
using value_type = std::optional<std::string>;
value_type value;
operator const value_type&() const { return value; }
rmap& operator=(value_type&& v) { value = v; return *this; }
friend std::ostream& operator<<(std::ostream& os, rmap& m) { return os << (m.value ? *m.value : "(nil)"); }
};
int main()
{
rmap m;
m["hello"]["world"] = std::nullopt;
m["vive"]["le"]["cassoulet"] = "Obama";
std::cout << m["does not exist"] << '\n'; // nil
std::cout << m["hello"]["world"] << '\n'; // nil
std::cout << m["vive"]["le"]["cassoulet"] << '\n'; // Obama
}
Вы можетеОтрегулируйте по своему вкусу немного синтаксического сахара.