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;
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;
2
c++17 introduced the type std::any
, a container capable of storing 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 one std::any
for its original type with std::any_cast
.
In your problem, the type of the element value of the map_exemplo
could be defined as std::any
, then every time you create a new entry in map_exemplo
, the type of the element will not matter. Since not everything is a bed of roses, however, to iterate over the elements in this container, you will need to encode 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 geared to replace the use of type void *
to save user data. In your case, type std::variant
would be better for your needs, because with it you can define which types are expected, and the 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 need to be constructive.
Sensational your answer, a little doubt, the types of a Variant can be selected at compilation time?
@cYeR, if by "selected at compile time" you say "define which types a Variant data accepts," then yes, this is required. Now, if you meant if "it is possible to use Variant in constant expressions," the answer is also yes, the Std::Variant constructors sane constexpr
, except for the copycat.
Browser other questions tagged c++ map c++17
You are not signed in. Login or sign up in order to post.
Can you give an example where you would use this ? Templates are usually used in classes or functions where this example would make sense and work perfectly.
– Isac
If I understand, you want to know if there is a way to let the type of each element in the map be any one (i.e. heterogeneous)?
– Mário Feroldi
I got it, but I need to use a separate for each type, is there any way to access all the elements in a single for? Isac an example(With the problem I described above): https://paste.ofcode.org/Rfd42R7EW2zqbP7z5A3vVy That’s exactly it @Márioferoldi
– cYeR
It seems to me that your real doubt does not play with the question. The goal of templates is to allow defining a specific type to be used in a function or class, which can vary when an object instantiates or calls the function. In the case and according to what you wrote in the existing answer your goal is to have values of different types in the same
map
.– Isac
@Isac, nitpick: template also applies to top-level variables.
– Mário Feroldi