Partial ordering of function templates containing template parameter packs

三世轮回 提交于 2019-12-04 16:55:01
Barry

First step in overload resolution is finding all the candidates. For the call g(Tuple<int>()), there are three viable candidates:

g(Tuple<int>); // #1: [Types = {int}]
g(Tuple<int>); // #2: [T1 = int, Types = {}]
g(Tuple<int>); // #3: [T1 = int, Types = {}]

All three are equally viable candidates from the perspective of conversion sequences (since, of course, they all take the same argument which is an Exact Match for the input). They are all function template specializations, so we can't differentiate on that basis either.

So we're left with function template partial ordering. We synthesize types for each of the overloads and attempt to perform template deduction with our synthesized types against each of the other overloads. The simpler comparison is (1) vs (2) and (1) vs (3). There, we have [temp.deduct.partial]:

If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.

Since we transform Types... into UniqA..., and the first parameter is T1, type deduction fails. That makes (2) and (3) both more specialized than (1). So now we compare (2) and (3).

First, can we deduce (2) from (3)?

template <class T1, class... Types> void g(Tuple<T1, Types...> );

g(Tuple<Uniq3, Uniq3Pack&...>());

Sure, no problem T1 == Uniq3 and Types... == Uniq3Pack&.... Next, we try the other direction:

template <class T1, class... Types> void g(Tuple<T1, Types&...> );

g(Tuple<Uniq2, Uniq2Pack...>());

This fails, since Uniq2Pack isn't a pack of reference types and Types&... is. Since deduction only succeeds in one direction, that makes (3) the more specialized overload.

As it's the last one standing, (3) is the best viable candidate. It may seem counterintuitive, since we're not actually calling it with a reference type - but it's still the best choice.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!