How to use a template as a type on a map?

0

Is there any way to use template as type in a map in C ++ 17?

template<typename T>
std::map<std::string, T/* tipo desconhecido, pode ser qualquer tipo */> map_exemplo;
    
asked by anonymous 01.10.2018 / 18:39

1 answer

2

introduced the type std::any , a container capable of saving objects of any kind *. Examples:

#include <any>
#include <string>

int main() {
    std::any a = 42; // int
    a = 3.14f; // float
    a = true; // bool
    a = std::string("Hello, World!"); // std::string
}

You can redeem the value of a std::any to its original type with std::any_cast .

In your problem, the element value type of map_exemplo could be set to std::any , so every time you create a new entry in map_exemplo , the element type will not matter. Like everything is not a sea of roses, however, to iterate over the elements of this container, you will have to code the types you expect the elements to have:

#include <map>
#include <any>
#include <string>

int main() {
    std::map<std::string, std::any> map_exemplo;

    map_exemplo["a"] = 42;
    map_exemplo["b"] = 3.14f;
    map_exemplo["c"] = true;

    for (const auto &[chave, valor] : map_exemplo) {
        if (auto ptr = std::any_cast<int*>(&valor)) {
            // ...
        }
        else if // ...
    }
}

The purpose of std::any is more intended to replace the use of type void * to save user data. In your case, the type std::variant would suit your needs better, because with it you can define which types are expected, and access to objects is done with std::visit :

#include <map>
#include <variant>
#include <string>
#include <cstdio>

// Classe ajudante para sobrecarregar lambdas.
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

int main() {
    std::map<std::string, std::variant<int, float, bool>> map_exemplo;

    map_exemplo["a"] = 42;
    map_exemplo["b"] = 3.14f;
    map_exemplo["c"] = true;

    for (const auto &[chave, valor] : map_exemplo) {
        std::visit(overloaded {
            [] (int i) { std::printf("int: %d\n", i); },
            [] (float f) { std::printf("float: %f\n", f); },
            [] (bool b) { std::printf("bool: %s\n", b ? "true" : "false"); }
        }, valor);
    }
}

* Some rules apply here so that an object can be saved by a std::any , such as satisfying the requirement to be constructive.

    
02.10.2018 / 18:52