I have a project where I'm putting objects in an unordered_map
that can logically chain together with other objects in the map. To represent this chain, I store a reference to the next object in the chain's map key, so I end up with something resembling a linked list within the map:
class Foo
{
int *next;
// other fields, methods, etc.
};
std::unordered_map<int, Foo> foos;
I've added a helper method that follows the linked list for an object and returns pointers to the following objects in a vector
:
class Foo
{
int *next;
std::vector<Foo *> following(std::unordered_map<int, Foo> &foos) const
{
std::vector<Foo *> result;
const Foo *current = this;
while (current->next)
{
auto nextIt = foos.find(*current->next);
if (nextIt == foos.end()) break;
result.push_back(&nextIt->second);
current = &nextIt->second;
}
return result;
}
I also want to have a version of this helper that works on a const
reference to the map and returns const
pointers, i.e. std::vector<const Foo *> following(const std::unordered_map<int, Foo> &foos) const
. I can of course create this just by duplicating the code, but is there a way to achieve this without duplication through templating or something similar?
const_cast
), it won't work here because OP wants the inner type of the return value to be conditionally-const. Aconst_cast
can't do that and a C-style cast orreinterpret_cast
will result in undefined behavior. – Pantomimistthis
that is conditionally-const here. – Pantomimistconst_cast
is perfectly safe in this context. It is used in countless codebases in this exact way. It is safe because it is restricted to this single overload and it casts non-const into const, not the other way around. Of course, in the code as OP has written it, this method and deducing this are not an option but he might adjust his code if his application allows it. I have listed him all the possible options. "emulating deducing this" is basically what you have done in your answer and that is exactly what I had in mind. – Jacklighter