You have a ton of options depending on what you're doing.
For one, you could just standardize the code a bit more. Use the same naming convention everywhere. Then your templates will just work (assuming you write them correctly):
template <typename T>
void stuff (T& t) {
t.pos = vec3(0,0,0);
}
You could also use inheritance, though this is almost certainly not what you want:
struct base {
vec3 pos;
};
struct foo : base {
};
struct bar : base {
};
void stuff(base& b) {
b.pos = vec3(0,0,0);
}
A far more natural approach may be to just pass in the member values you need, assuming you're only using a small number of them. If you have a lot, use composition/aggregation.
struct transform {
vec3 pos;
vec3 scale;
};
struct foo {
transform trans;
};
struct bar {
transform TransSpelledDifferently;
};
void stuff(transform& t) {
t.pos = vec3(0,0,0);
}
foo f;
bar b;
stuff(f.trans);
stuff(b.TransSpelledDifferently);
Failing that, you can use accessor functions outside of your class, which plays well with ADL.
vec3& get_pos(PINT& p) { return p.pos; }
vec3& get_pos(PNTWB& p) { return p.Pos; }
template <typename T>
void stuff1(T& t) {
get_pos(t) = vec3(0,0,0);
}
void stuff2(vec3& pos) {
pos = vec3(0,0,0);
}
stuff2(get_pos(whatever));
There's more ways, too, though some get particularly advanced/complex without much benefit over the above approaches.
C++ is a multi-paradigm language. There are many ways to solve any problem. So long as you consistently apply the particular paradigms in your code (mix them as needed, only when needed), this doesn't get too confusing.