demangle.go
func (st *state) templateParam() AST {
	if len(st.templates) == 0 {
		st.fail("template parameter not in scope of template")
	}
	off := st.off

	st.checkChar('T')
	n := st.compactNumber()

	template := st.templates[len(st.templates)-1]

	if template == nil {
		// We are parsing a cast operator.  If the cast is
		// itself a template, then this is a forward
		// reference.  Fill it in later.
		return &TemplateParam{Index: n, Template: nil}
	}

	if n >= len(template.Args) {
		st.failEarlier(fmt.Sprintf("template index out of range (%d >= %d)", n, len(template.Args)), st.off-off)
	}

	return &TemplateParam{Index: n, Template: template}
}
func (st *state) templateParam() AST {
	if len(st.templates) == 0 {
		st.fail("template parameter not in scope of template")
	}
	off := st.off

	st.checkChar('T')
	n := st.compactNumber()

	template := st.templates[len(st.templates)-1]

	if template == nil {
		// We are parsing a cast operator.  If the cast is
		// itself a template, then this is a forward
		// reference.  Fill it in later.
		return &TemplateParam{Index: n, Template: nil}
	}

	if n >= len(template.Args) {
		st.failEarlier(fmt.Sprintf("template index out of range (%d >= %d)", n, len(template.Args)), st.off-off)
	}

	return &TemplateParam{Index: n, Template: template}
}
// <template-param> ::= T_
//                  ::= T <(parameter-2 non-negative) number> _
//
// When a template parameter is a substitution candidate, any
// reference to that substitution refers to the template parameter
// with the same index in the currently active template, not to
// whatever the template parameter would be expanded to here.  We sort
// this out in substitution and simplify.