I am wondering whether it is possible to use a template as a key for a map. For instance:
std::map< <T> , Node> nodes;
In essence, what I want to do is be able to have a bunch of nodes that contain arbitrary types data, and are keyed by that data. I think I could do it by converting said data to binary and keying by that, but that is messy and I want to avoid it.
To clarify, I want to be able to use a variable of any type as the key. For example if I have 2 nodes, one that contains an int as its data, and another that contains a Foo as its data, I want to be able to put those in the same map using their data as the key. Maybe a map is not what I want, I am not sure...
Thoughts? Thanks!
If you didn't disabled RTTI explicitly, refer to nogard's answer. Standard type id is garanteed to be unique for a whole program across DLL. This is not true for the address of a function.
What I usually do is this:
template<typename T>
void type_id(){}
using type_id_t = void(*)();
Then, I use it like this:
std::map<type_id_t, Node> nodes;
nodes[type_id<AType>] = Node{...};
nodes[type_id<BType>] = Node{...};
Of course, this can be enhanced with variable template from C++14.
Sorry, I just re-read the question and I understand it better.
What you want is std::any
, but it's C++17 only. You can use boost::any
instead.
It will look like this:
std::map<std::any, Node> nodes;
nodes.emplace("string as key", Node{});
nodes.emplace(23, Node{});
It should work as long as the map can somehow order instances of std::any
. If not, you can use hash map instead:
std::unordered_map<std::any, Node> nodes;
Then it will work as long as the map can hash an any.
I think for this purpose it's much easier to use std::type_info
for the types:
std::map<std::type_info, std::string> m;
m[typeid(int)] = "integer";
But this really depends on what you want to achieve, it's still unclear to me. Hope that helps
At least if I understand what you want, the short answer is no.
The keys in a map must be ordered--that is, you must define for any pair of keys A and B, you must define an ordered relationship where either A is less than B, or B is less than A, or the two keys are equivalent.
Given two keys of entirely arbitrary types there's not going to be a defined way of comparing them. Therefore, you can't use them as keys in for a map.
To get something sort of close, you'll need to define some specific set of types you want to support. Then you can define something that's (roughly) a union of all the types you want to support. That alone won't be enough though--you'll also have to define ordering. Depending on what you're trying to accomplish, you might have (for example) an ID in every one of those objects, and order them by ID. Alternatively, you might define an ordering between objects, so (for example) every Person
sorts before every Dog
, which sorts before every Dream
, and so on. Then you'll have to define an ordering within each type about like you usually would.
I'd warn, however, that this typically involves quite a bit of extra work, and provides very little value in return. I'd say well over 90% of the time I've seen people (try to) do this, it's been a mistake that worked out poorly at best. If at all possible, I'd try to find some other approach to whatever problem you're trying to solve.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With