Assume I have a function template like this:
template<class T>
inline
void
doStuff(T* arr)
{
// stuff that needs to use sizeof(T)
}
Then in another .h
filee I have a template class Foo
that has:
public: operator T*() const;
Now, I realize that those are different Ts. But If I have a variable Foo<Bar> f
on the stack, the only way to coerce it to any kind of pointer would be to invoke operator T*()
. Yet, if call doStuff(f)
, GCC complains that doStuff
can't take Foo<Bar>
instead of automatically using operator T*()
to coerce to Bar*
and then specializing the function template with Bar
as T
.
Is there anything I can do to make this work with two templates? Or does either the argument of the template function have to be a real pointer type or the template class with the coercion operator be passed to a non-template function?
GCC is correct. In template arguments only exact matches are considered, type conversions are not. This is because otherwise an infinite (or at least exponential) amount of conversions could have to be considered.
If Foo<T> is the only other template that you're going to run in to, the best solution would be to add:
template<typename T> inline void doStuff(const Foo<T>& arr) {
doStuff(static_cast<T*>(arr));
}
If you are having this issue with a lot of templates, this one should fix it:
#include <boost/type_traits/is_convertible.hpp>
#include <boost/utility/enable_if.hpp>
template<template <typename> class T, typename U> inline typename boost::enable_if<typename boost::is_convertible<T<U>, U*>::type>::type doStuff(const T<U>& arr) {
doStuff(static_cast<U*>(arr));
}
It's a bit verbose though ;-)