Movatterモバイル変換


[0]ホーム

URL:


This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-12-20


214. Partial ordering of function templates is underspecified

Section:13.7.7.3  [temp.func.order]    Status:CD1    Submitter:Martin von Loewis/Martin Sebor    Date:13 Mar 2000

[Voted into WP at October 2003 meeting.]

In 13.7.7.3 [temp.func.order], partial ordering is explained interms of template argument deduction. However, the exact procedure fordoing so is not specified. A number of details are missing, they areexplained as sub-issues below.

  1. 13.7.7.3 [temp.func.order] paragraph 2 refers to13.10.3 [temp.deduct] for argument deduction. This is thewrong reference; it explains how explicit arguments are processed(paragraph 2) and how function parameter types are adjusted (paragraph3). Neither of these steps is meaningful in the context of partialordering. Next in deduction follows one of the steps in 13.10.3.2 [temp.deduct.call], 13.10.3.3 [temp.deduct.funcaddr], 13.10.3.4 [temp.deduct.conv], or 13.10.3.6 [temp.deduct.type]. The standarddoes not specify which of these contexts apply to partialordering.
  2. Because 13.10.3.2 [temp.deduct.call] and 13.10.3.4 [temp.deduct.conv] both start with actual function parameters, it ismeaningful to assume that partial ordering uses 13.10.3.6 [temp.deduct.type], which only requires types. With that assumption,the example in 13.7.7.3 [temp.func.order] paragraph 5 becomesincorrect, considering the two templates
        template<class T> void g(T);  // #1    template<class T> void g(T&); // #2
    Here, #2 is at least as specialized as #1: With a synthetic typeU, #2 becomesg(U&); argument deduction against#1 succeeds withT=U&. However, #1 is not at least asspecialized as #2: Deducingg(U) againstg(T&)fails. Therefore, the second template is more specialized than thefirst, and the callg(x) is not ambiguous.
  3. According to John Spicer, the intent of the partial ordering wasthat it uses deduction as in a function call (13.10.3.2 [temp.deduct.call]), which is indicated by the mentioning of "exactmatch" in 13.7.7.3 [temp.func.order] paragraph 4. If that isindeed the intent, it should be specified how values are obtained forthe step in 13.10.3.2 [temp.deduct.call] paragraph 1, where thetypes of the arguments are determined. Also, since 13.10.3.2 [temp.deduct.call] paragraph 2 drops references from the parametertype, symmetrically, references should be dropped from the argumenttype (which is done in Clause 7 [expr] paragraph 2, for a truefunction call).
  4. 13.7.7.3 [temp.func.order] paragraph 4 requires an "exactmatch" for the "deduced parameter types". It is not clear whether thisrefers to the template parameters, or the parameters of the templatefunction. Considering the example
        template<class S> void g(S);  // #1    template<class T> void g(T const &); // #3
    Here, #3 is clearly at least as specialized as #1. To determinewhether #1 is at least as specialized as #3, a unique typeUis synthesized, and deduction ofg<U>(U) is performedagainst #3. Following the rules in 13.10.3.2 [temp.deduct.call],deduction succeeds withT=U. Since the template argument isU, and the deduced template parameter is alsoU, wehave an exact match between the template parameters. Even though theconversion fromU toU const & is an exactmatch, it is not clear whether the added qualification should be takeninto account, as it is in other places.

Issue 200 covers a related issue,illustrated by the following example:

    template <class T> T f(int);    template <class T, class U> T f(U);    void g() {        f<int>(1);    }

Even though one template is "obviously" more specialized than theother, deduction fails in both directions because neither functionparameter list allows template parameterT to be deduced.

(See alsoissue 250.)

Nathan Sidwell:

13.7.7.3 [temp.func.order] describes the partial ordering of functiontemplates. Paragraph 5 states,

A template is more specialized than another if, andonly if, it is at least as specialized as the othertemplate and that template is not at least asspecialized as the first.
To paraphrase, given two templates A & B, if A's templateparameters can be deduced by B, but B's cannot be deduced byA, then A is more specialized than B. Deduction is done asif for a function call. In particular, except for conversionoperators, the return type is not involved in deduction.This leads to the following templates and use beingunordered. (This example is culled from G++ bug report 4672http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=4672)
  template <typename T, class U> T checked_cast(U from); //#1  template <typename T, class U> T checked_cast(U * from); //#2  class C {};  void foo (int *arg)  {    checked_cast <C const *> (arg);  }
In the call,

#1 can be deduced with T = 'C const *' and U = 'int *'

#2 can be deduced with T = 'C const *' and U = 'int'

It looks like #2 is more specialized that #1, but13.7.7.3 [temp.func.order] does not make it so, as neither template candeduce 'T' from the other template's function parameters.

Possible Resolutions:

There are several possible solutions, however throughexperimentation I have discounted two of them.

Option 1:

When deducing function ordering, if the return type of one ofthe templates uses a template parameter, then return typesshould be used for deduction. This, unfortunately, makesexisting well formed programs ill formed. For example

  template <class T> class X {};  template <class T> X<T> Foo (T *);// #1  template <class T> int Foo (T const *); // #2  void Baz (int *p1, int const *p2)  {    int j = Foo (p2); //#3  }
Here, neither #1 nor #2 can deduce the other, as the returntypes fail to match. Considering only the function parametersgives #2 more specialized than #1, and hence makes the call#3 well formed.

Option 2:

As option 1, but only consider the return type when deducingthe template whose return type involves template parameters.This has the same flaw as option 1, and that example issimilarly ill formed, as #1's return type 'X<T,0>' fails tomatch 'int' so #1 cannot deduce #2. In the converse direction,return types are not considered, but the function parametersfail to deduce.

Option 3:

It is observed that the original example is only callablewith a template-id-expr to supply a value for the first,undeducible, parameter. If that parameter were deducible itwould also appear within at least one of the functionparameters. We can alter paragraph 4 of [temp.func.order]to indicate that it is not necessary to deduce the parameterswhich are provided explicitly, when the call has the formof a template-id-expr. This is a safe extension as it onlyserves to make ill formed programs well formed. It is alsoin line with the concept that deduction for functionspecialization order should proceed in a similar manner tofunction calling, in that explicitly provided parametervalues are taken into consideration.

Suggested resolution:

Insert after the first sentence of paragraph 4 in13.7.7.3 [temp.func.order]

Should any template parameters remain undeduced, andthe function call be of the form of atemplate-id-expr,those template parameters provided in thetemplate-id-expr may be arbitrarily synthesized priorto determining whether the deduced arguments generatea valid function type.

See alsoissue 200.

(April 2002) John Spicer and John Wiegley have written apaper on this. See 02-0051/N1393.

Proposed resolution (October 2002):

Change 13.7.7.3 [temp.func.order] paragraph 2 to read:

Partial ordering selects which of two function templates is morespecialized than the other by transforming each template in turn(see next paragraph) and performing template argument deductionusing the function parameter types, or in the case of a conversionfunction the return type. The deduction process determines whetherone of the templates is more specialized than the other. If so, themore specialized template is the one chosen by the partial orderingprocess.

Change 13.7.7.3 [temp.func.order] paragraph 3 to read:

To produce the transformed template, for each type, non-type, or templatetemplate parameter synthesize a unique type, value, or class templaterespectively and substitute it for each occurrence of that parameterin the function type of the template.

Change 13.7.7.3 [temp.func.order] paragraph 4 to read(note: the section reference should refer to the section added to13.10.3 [temp.deduct] below):

Using the transformed function template's function parameter list, orin the case of a conversion function its transformed return type,perform type deduction against the function parameter list (or returntype) of the other function. The mechanism for performing thesedeductions is given in 14.8.2.x.

Remove the text of 13.7.7.3 [temp.func.order] paragraph 5 butretain the example. The removed text is:

A template is more specialized than another if, and only if, it isat least as specialized as the other template and that template is notat least as specialized as the first.

Insert the following section before 14.8.2.5(Note that this would either be a new 14.8.2.4, or would be givena number like 14.8.2.3a. If neither of these is possible froma troff point of view, this could be made 14.8.2.5.)

Deducing template arguments when determining the partial orderingof function templates (temp.deduct.partial)

Template argument deduction is done by comparing certain types associated withthe two function templates being compared.

Two sets of types are used to determine the partial ordering. For each ofthe templates involved there is the original function type and thetransformed function type. [Note:The creation of the transformed type isdescribed in 13.7.7.3 [temp.func.order].]The deduction process uses thetransformed type as the argument template and the original type of theother template as the parameter template. This process is done twicefor each type involved in the partial ordering comparison: once usingthe transformed template-1 as the argument template and template-2 asthe parameter template and again using the transformed template-2 asthe argument template and template-1 as the parameter template.

The types used to determine the ordering depend on the context in whichthe partial ordering is

Each type from the parameter template and the corresponding type from theargument template are used as the types ofP andA.

Before the partial ordering is done, certain transformations are performedon the types used for partial ordering:

If bothP andA were reference types (before being replacedwith the type referred to above), determine whichof the two types (if any) is more cv-qualified than the other; otherwisethe types are considered to be equally cv-qualified for partial orderingpurposes. The result of this determination will be used below.

Remove any top-level cv-qualifiers:

Using the resulting typesP andA the deduction is thendone as described in (13.10.3.6 [temp.deduct.type]).If deduction succeeds for a given type,the type from the argument template is considered to be at least as specializedas the type from the parameter template.

If, for a given type, deduction succeeds in both directions (i.e., thetypes are identical after the transformations above) if the type fromthe argument template is more cv-qualified than the type from theparameter template (as described above) that type is considered to bemore specialized than the other. If neither type is more cv-qualifiedthan the other then neither type is more specialized than the other.

If for each type being considered a given template is at least as specializedfor all types and more specialized for some set of types and theother template is not more specialized for any types or is notat least as specialized for any types, thenthe given template is more specialized than the other template. Otherwise, neither templateis more specialized than the other.

In most cases, all template parameters must have values in order fordeduction to succeed, but for partial ordering purposes a templateparameter may remain without a value provided it is not used in thetypes being used for partial ordering. [Note:A template parameter usedin a non-deduced context is considered used.]

[Example:

template <class T> T f(int);        // #1template <class T, class U> T f(U); // #2void g() {    f<int>(1);  // Calls #1}
--end example]




[8]ページ先頭

©2009-2026 Movatter.jp