You say you can not modify the structs... but are they raw structs or do they have constructors?
If they are raw structs, what you can do is to use the numero uno solution for everything in computers: add one extra layer of indirection.
Instead of having larger
compare the Ts directly and have to overload or specialize each one, have a new larger2
that compares "completed" versions of the structs, where the completed version is computed more or less generically:
// Your original one, won't work
template<typename T>
bool larger(T a, T b){
if(a.x>b.x&&a.y>b.y&&a.z>b.z) return true;
return false;
}
struct Txy {
int x, y;
};
struct Txz {
int x, z;
};
struct Txyz {
int x, y, z;
};
// This struct "completizes" Ts, adding manually the missing members.
// Note for this to work, we are forced to add constructors to Completizer
// (unless I am missing something)
template <typename T>
struct Completizer: T {
// this constructor is needed
Completizer (T const& t): T(t) {}
};
template<> struct Completizer<Txy>: Txy {
int z;
Completizer (Txy const& t): Txy(t), z(0) {}
};
template<> struct Completizer<Txz>: Txz {
int y;
Completizer (Txz const& t): Txz(t), y(0) {}
};
// this is the thing that actually does the magic
template<typename T>
bool larger2_impl(Completizer<T> const& a, Completizer<T> const& b) {
if(a.x>b.x&&a.y>b.y&&a.z>b.z) return true;
return false;
}
// the trick here is to have our "larger" function not compare the Ts directly,
// but do so by means of Completizer<T>
template<typename T>
bool larger2(T const& a, T const& b) {
return larger2_impl(Completizer<T>(a), Completizer<T>(b));
}
int main () {
Txy xy1 = {1, 2}, xy2 = {2, 3};
Txz xz1 = {1, 2}, xz2 = {2, 3};
Txyz xyz1 = {1, 2, 3}, xyz2 = {2, 3, 4};
// only here to avoid warnings
(void)xy1; (void)xy2;
(void)xz1; (void)xz2;
//larger(xy1, xy2); // does not compile
larger2(xyz1, xyz2); // compiles
larger2(xy1, xy2); // compiles
larger2(xz1, xz2); // compiles
}
The advantage of this method is that it scales somewhat easier if you start adding more members, since you can derive Completizer<Txyzw>
from Completizer<Txyz>
.