this is a little different to what you suggested (namely the second "typename TTrainer"); is it correct?
There's no difference. Naming the nested template parameter TTrainer doesn't change anything, it's still unrelated to the first template parameter TTrainer.
And then simply referring to T as T<TTrainer> in the code; is that legal?
template <typename TTrainer, template <typename> typename T, template <typename> typename TParent>
struct graveyard {
graveyard(TParent<TTrainer>*); // constructor
TParent<TTrainer>* pTParent; // parent member of this graveyard
T<TTrainer>* pop(); // resurrect/create T
void push(T<TTrainer>*); // kill T
T<TTrainer>* grave[]; // array of Ts in the graveyard
size_t grave_length; // number of pushed Ts in the graveyard
};
template <template T, template TParent>
struct graveyard {
graveyard(TParent*); // constructor
TParent* pTParent; // parent member of this graveyard
T* pop(); // resurrect/create T
void push(T*); // kill T
T* grave[]; // array of Ts in the graveyard
size_t grave_length; // number of pushed Ts in the graveyard
};
then if T is of type brain<TTrainer>, the line T* pop(); for example will return a type brain<TTrainer> anyway, right?