I am having trouble understanding why the following does not compile. I have the following code like so (some code ommited):
Header:
template <typename KeyType, typename ElementType>
class TUnorderedMap
{
public:
ElementType* Find(const KeyType Key);
const ElementType* Find(const KeyType Key) const;
};
struct Foo
{
};
Source file:
void Lookup()
{
TUnorderedMap <Foo*, Foo> NodeToWidgetLookup;
Foo TempFoo;
const Foo* SelectionTarget = &TempFoo;
// Issue here in this call
NodeToWidgetLookup.Find(SelectionTarget);
// Issue here in this call
NodeToWidgetLookup.Find(SelectionTarget);
}
Error message: What is the issue here? Why is neither of the Find functions accepted?
CodePudding user response:
What is the issue here? Why is neither of the Find functions accepted?
With the given instantiation
TUnorderedMap <Foo*, Foo> NodeToWidgetLookup;
The function Find
expects a const pointer Foo *const
:
const ElementType* Find(Foo* const Key) const;
While you are trying to pass a non-const pointer to const argument const Foo*
:
const Foo* SelectionTarget
You can either change the template arguments like this:
TUnorderedMap <const Foo*, Foo> NodeToWidgetLookup;
Or make your argument point to a non-const instance:
Foo* SelectionTarget;
If you want to take all pointer overloads, you may want to declare an overload that is a function template itself:
template<typename Key>
const ElementType* Find(const Key* key) const {
static_assert(std::is_same<Key*, KeyType>::value, "The types don't match");
...
}
The template ignores cv-qualifiers of the pointed to object of and the (outermost) pointer part of the argument, but it won't be applicable for non-pointer types.
Thanks to overload resolution rules you also can mix it with a non-template overload:
ElementType* Find(const KeyType Key);
const ElementType* Find(const KeyType Key) const;
template<typename Key> const ElementType* Find(const Key* key) const;
But be advised, that non-template functions in this scenario precede the function template in the overload resolution candidate list.