This could be very silly…
If I have such a template class A,
template <class T1, class T2>
struct A
{
T1 a;
T2 b;
};
and a function works on it,
template <class T1, class T2>
void foo(A<T1, T2> *p)
{
}
now I subclass A,
struct B : A<int, int>
{
};
B b[100];
I can not deduce template parameter…
foo(b);
and I have to write like this,
foo((B *)b);
or like this,
foo<int, int>(b);
and now something more,
I wish foo can accept something T other than A and treat them as A
template <class T>
struct A<T, void>
{
T a;
};
template <class T>
void foo(T *p)
{
foo((A<T, void> *)p);
}
now unless I write like this, the later foo is called…
foo<int, int>(b);
- How can I make deducing template parameters from array of subclass easier?
- How can I make subclass have higher priority than other class when locating overloaded function?
This seems will do
template <class T>
struct is_A_derived
{
typedef char (&yes)[1];
typedef char (&no)[2];
template <class T1, class T2>
static yes test(A<T1, T2> *);
static no test(...);
template <class T1, class T2>
static A<T1, T2> get_type(A<T1, T2> *);
static A<T, void> get_type(...);
template <class T1, class T2>
static A<T1, T2> base_type(A<T1, T2> *);
static int base_type(...); // guess or maybe hope this "int" is never used
static const bool value = sizeof(test((T *)0)) == sizeof(yes);
static const bool identical = value && sizeof(base_type((T *)0)) == sizeof(T);
typedef typename std::conditional<identical, decltype(get_type((T *)0)), A<T, void>>::type type;
};
In the first case, there is actually a danger of decaying an array of B to an A* pointer, in case you happen do to pointer arithmetic on the A* pointer.
It surprises me that it doesn’t resolve but could be a nice safety feature, just in case you are planning to perform a function over an array of A, which won’t work with an array of B.
You could do
foo( &b[0] )rather than casting or explicit templating.In the latter case you are now complicating things with a function foo on your T* if it has the same name as the function on the A template.
Once you add the second foo, the call on B will indeed choose the second foo because it now becomes a perfect match. The subclass can be given a higher priority with clever SFINAE techniques to see if it is an A or not. Generally though I would avoid using this unless you really have to.