On Mon, 1 Jun 2026, Eczbek wrote:

> On 6/1/26 16:33, Jason Merrill wrote:
> > This assumes a template with a single template parameter; it doesn't work 
> > for e.g.
> > 
> > struct A {
> >   template<typename T, typename U>
> >   operator T U::*() {
> >     return 0;
> >   }
> > };
> > 
> > int main() {
> >   (void) &A::operator int A::*;
> > }
> > 
> > to handle the general case you need to deduce the template arguments.
> 
> Thanks, I did not consider multiple template parameters. Would this be 
> similar to what TEMPLATE_ID_EXPR does below, or is there some existing helper 
> that should be used? I'm not sure how to do this.

There are a couple of entrypoints to deduction, all of which ultimately
call the main workhorse unify.  For simplicity I think we could get away
with calling unify directly from resolve_nondeduced_context with

  tparms = DECL_TEMPLATE_PARMS of the conversion function template
  targs = empty TREE_VEC same length as DECL_TEMPLATE_PARMS
  parm = return type of the template
  arg = BASELINK_OPTYPE
  strict = UNIFY_ALLOW_NONE (I think?)

If unify succeeds, then 'targs' will contain the deduced template
arguments that we need to instantiate the conversion function template
with.

So for

  struct A {
    template<class T, class U>
    operator B<T*, U&>();
  };

  int main() {
    &A::operator B<int*, char&>;
  }

we need to call unify with (where {} is shorthand for a TREE_VEC)

  tparms = {T, U}
  targs = {NULL, NULL}
  parm = B<T*, U&>
  arg = B<int*, char&>

which should succeed and fill in targs with {int, char}.  Instantiating
the template with {int, char} yields the correct specialization
operator B<int*, char&>.

Reply via email to