Movatterモバイル変換


[0]ホーム

URL:


Issue 1391 - WG21 CWG Issues
Title
Conversions to parameter types with non-deduced template arguments
Status
cd4
Section
13.10.2 [temp.arg.explicit]
Submitter
Jason Merrill

Created on2011-09-08.00:00:00 last changed109 months ago

Messages

msg6081 (view)
Date: 2015-10-15.00:00:00

[Moved to DR at the October, 2015 meeting.]

msg6080 (view)
Date: 2015-11-10.00:00:00

Additional note October, 2015:

See alsoissue 1939.

msg5466 (view)
Date: 2015-05-15.00:00:00

Proposed resolution (May, 2015):

  1. Change 13.10.3.2 [temp.deduct.call] paragraph 1as follows:

  2. Template argument deduction is done by comparing eachfunction template parameter type (callitP)that containstemplate-parametersthat participate in template argument deduction withthe type of the corresponding argument of the call (callitA) as described below. IfP is adependent type, removing references and cv-qualifiersfromP givesstd::initializer_list<P'> orP'[N]for someP' andN and the argument is anon-empty initializer list (9.5.5 [dcl.init.list]),then deduction is performed instead for each element of theinitializer list, takingP' as a function templateparameter type and the initializer element as its argument,and in theP'[N] case, ifN is a non-typetemplate parameter,N is deduced from the length ofthe initializer list. Otherwise, an initializer listargument causes the parameter to be considered a non-deducedcontext (13.10.3.6 [temp.deduct.type]). [Example:...
  3. Delete the note in 13.10.3.2 [temp.deduct.call] paragraph 4:

  4. [Note: as specified in 13.10.2 [temp.arg.explicit],implicit conversions will be performed on a functionargument to convert it to the type of the correspondingfunction parameter if the parameter containsnotemplate-parameters that participate in templateargument deduction. Such conversions are also allowed, inaddition to the ones described in the precedinglist. —end note]
  5. Add the following as a new paragraph at the end of13.10.3.2 [temp.deduct.call]:

  6. If deduction succeeds for all parameters that containtemplate-parameters that participate in templateargument deduction, and all template arguments areexplicitly specified, deduced, or obtained from defaulttemplate arguments, remaining parameters are then comparedwith the corresponding arguments. For each remainingparameterP with a type that was non-dependentbefore substitution of any explicitly-specified templatearguments, if the corresponding argumentA cannotbe implicitly converted toP, deduction fails.[Note: Parameters with dependent types in which notemplate-parameters participate in templateargument deduction, and parameters that became non-dependentdue to substitution of explicitly-specified templatearguments, will be checked during overload resolution.—end note] [Example:

      template <class T> struct Z {    typedef typename T::x xx;  };  template <class T> typename Z<T>::xx f(void *, T); // #1  template <class T> void f(int, T);                 // #2  struct A {} a;  int main() {    f(1, a);                                         // OK, deduction fails for #1 because there is no conversion fromint tovoid*  }

    end example]

  7. Change 13.10.3.5 [temp.deduct.partial] paragraph 4 as follows:

  8. Each type nominated above from the parameter template andthe corresponding type from the argument template are usedas the types ofP andA.If a particularP contains notemplate-parameters thatparticipate in template argument deduction, thatPis not used to determine the ordering.
  9. Change 13.10.3.6 [temp.deduct.type] paragraph 4 as follows:

  10. In most cases, the types, templates, and non-type valuesthat are used to composeP participate in templateargument deduction. That is, they may be used to determinethe value of a template argument, and the value sodetermined must be consistent with the values determinedelsewhere. In certain contexts, however, the value does notparticipate in type deduction, but instead uses the valuesof template arguments that were either deduced elsewhere orexplicitly specified. If a template parameter is used onlyin non-deduced contexts and is not explicitly specified,template argument deduction fails.[Note: Under13.10.3.2 [temp.deduct.call] and 13.10.3.5 [temp.deduct.partial],ifP contains notemplate-parameters thatappear in deduced contexts, no deduction is done, and soP andA need not have the same form.—end note]

This resolution also resolvesissue 1847.

msg4350 (view)
Date: 2013-04-15.00:00:00

Notes from the April, 2013 meeting:

The approach needed to accept this code appears to be doing theconvertibility check between deduction and substitution.

msg4115 (view)
Date: 2012-10-15.00:00:00

Notes from the October, 2012 meeting:

The position initially favored by CWG was that implicit conversionsare not considered during deduction but are only applied afterwards,so the second example is ill-formed, and that the normative wording ofthe referenced paragraph should be moved into the note. This approachdoes not handle some examples currently accepted by some implementations,however; for example:

   template <class T> struct Z {    typedef T::x xx;   };   template <class T> Z<T>::xx f(void *, T);   template <class T> void f(int, T);   struct A {} a;   int main() {     f(1, a); // If the implementation rules out the first overload              // because of the invalid conversion fromint tovoid*,              // the error instantiatingZ<A> will be avoided   }

Additional discussion is required.

msg3670 (view)
Date: 2022-02-18.07:47:23

According to 13.10.2 [temp.arg.explicit] paragraph 6,

Implicit conversions (7.3 [conv]) will beperformed on a function argument to convert it to the type of thecorresponding function parameter if the parameter type containsnotemplate-parameters that participate in template argumentdeduction. [Note: Template parameters do not participate intemplate argument deduction if they are explicitly specified...

But this isn't clear about when these conversions are done.Consider

    template<class T> struct A {       typename T::N n;    };    template<class T> struct B { };    template<class T, class T2>    void foo(const A<T>& r); // #1    template<class T>    void foo(const B<T>& r); // #2    void baz() {       B<char> b;       foo(b); // OK       foo<char>(b); // error    }

With the explicit template argument, the first parameter of #1no longer participates in template argument deduction, soimplicit conversions are done. If we check for the implicitconversion during the deduction process, we end up instantiatingA<char>, resulting in a hard error. If we waituntil later to check the conversion, we can reject #1 becauseT2 is not deduced and never need to consider theconversion.

But if we just accept the parameter and leave it up to normaloverload resolution to reject an unsuitable candidate, thatbreaks this testcase:

    template<class T>    struct A {       typename T::N n;    };    template<class T>    struct B { };    template <class T, class... U>    typename A<T>::value_t bar(int, T, U...);    template <class T>    T bar(T, T);    void baz()    {       B<char> b;       bar(b, b);    }

Here, if deduction succeeds, we substitute in the deducedarguments ofT = B<char>, U = { }, and end upinstantiatingA<B<char>>, which fails.

EDG and GCC currently reject the first testcase and accept thesecond; clang accepts both.

History
DateUserActionArgs
2017-02-06 00:00:00adminsetstatus: dr -> cd4
2015-11-10 00:00:00adminsetmessages: +msg6081
2015-11-10 00:00:00adminsetmessages: +msg6080
2015-11-10 00:00:00adminsetstatus: ready -> dr
2015-05-25 00:00:00adminsetmessages: +msg5466
2015-05-25 00:00:00adminsetstatus: drafting -> ready
2013-05-03 00:00:00adminsetmessages: +msg4350
2013-05-03 00:00:00adminsetstatus: open -> drafting
2012-11-03 00:00:00adminsetmessages: +msg4115
2011-09-08 00:00:00admincreate

[8]ページ先頭

©2009-2026 Movatter.jp