3

So, I am trying to make maps, which are infinitely nestable and I could use strings, ints, bools, etc. in it.

This is what I tried:

struct NMap;
struct NMap : std::map<std::string, std::variant<NMAP*, std::string, std::any>> {};
// ...
NMap* something;
something["lorem"]["ipsum"] = "Test";
                  ^ - No such operator []

Which is logical, std::variant doesn't have [] operator. Is there anyway to use std::variant in Nestable maps?

3 Answers3

6

Something simple and a bit weird:

#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, ...)
};

With a bit of sugar and some other tasteful adjustments, you can use it like you intend to:

#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
}

You can adjust to your taste with some syntactic sugar.

YSC
  • 38,212
  • 9
  • 96
  • 149
0

I suppose it would have to be something like:

(*std::get<NMap *>(something["lorem"]))["ipsum"] = "Test";
jdehesa
  • 58,456
  • 7
  • 77
  • 121
0

std::variant does not support recursive use, see this long answer. Note: it is not a beginner friendly topic.

NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277