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


425. Set of candidates for overloaded built-in operator with float operand

Section:12.5  [over.built]    Status:CD1    Submitter:Daniel Frey    Date:30 June 2003

[Voted into WP at March 2004 meeting.]

During a discussion over at the boost mailing list (www.boost.org), wecame across the following "puzzle":

  struct A {    template< typename T > operator T() const;  } a;  template<> A::operator float() const  {    return 1.0f;  }  int main()  {    float f = 1.0f * a;  }

The code is compiled without errors or warnings from EDG-based compilers(Comeau, Intel), but rejected from others (GCC, MSVC [7.1]). Thequestion: Who is correct? Where should I file the bug report?

To explain the problem: The EDG seems to see 1.0f*a as a call to theunambiguous operator*(float,float) and thus casts 'a' to 'float'. Theother compilers have several operators (float*float, float*double,float*int, ...) available and thus can't decide which cast isappropriate. I think the latter is the correct behaviour, but I'd liketo hear some comments from the language lawyers about the standard'spoint of view on this problem.

Andreas Hommel:Our compiler also rejects this code:

Error   : function call 'operator*(float, {lval} A)' is ambiguous'operator*(float, unsigned long long)''operator*(float, int)''operator*(float, unsigned int)''operator*(float, long)''operator*(float, unsigned long)''operator*(float, float)''operator*(float, double)''operator*(float, long double)''operator*(float, long long)'Test.cp line 12       float f = 1.0f * a;

Is this example really legal? It was my understanding that all candidatesfrom 12.5 [over.built] participate in overload resolution.

Daveed Vandevoorde:I believe the EDG-based compiler is right. Note that the built-in operator*requires "usual arithmetic conversions" (see7.6.5 [expr.mul] paragraph 2 andClause 7 [expr] paragaph 9). This means thatthere is no candidate taking (float, double) arguments: Only (float, float)or(double, double).

Since your first argument is of type float, the (float, float) case ispreferredover the (double, double) case (the latter would require a floating-pointpromotion).

Stave Adamczyk:Daveed's statement is wrong; as Andreas says, the prototypes in12.5 [over.built] paragraph 12have pairs of types, not the same type twice. However, the list ofpossibilities considered in Andreas' message is wrong also:12.5 [over.built] paragraph 12calls for pairs ofpromoted arithmetic types, and float is nota promoted type (it promotes to double -- see7.3.8 [conv.fpprom]).

Nevertheless, the example is ambiguous. Let's look at the overloadresolution costs. The right operand is always going to have auser-defined-conversion cost (the template conversion functionwill convert directly to the const version of the secondparameter of the prototype). The left operand is always going tohave a promotion (float --> double) or a standard conversion(anything else). So the cases with promotions are betterthan the others. However, there are several of thosecases, with second parameters of type int, unsigned int, long,unsigned long, double, and long double, and all of those areequally good. Therefore the example is ambiguous.

Here's a reduced version that should be equivalent:

  struct A {    template <typename T> operator T() const;  } a;  void f(double, int);  void f(double, unsigned int);  void f(double, long);  void f(double, unsigned long);  void f(double, double);  void f(double, long double);  int main() {    f(1.0f, a);  // Ambiguous  }

Personally, I think this is evidence that12.5 [over.built] doesn't reallydo quite what it should. But the standard is clear, if possiblyflawed.

Andreas Hommel:You are right, "float" is not a promoted arithmetic type, this is a bug inour compiler.

However, the usual arithmetic conversions(Clause 7 [expr] paragraph 9) do not promote the floatingpoint types, so

  float operator+(float, float);
is a legal built-in operator function, so I wonder if it shouldn't beincluded in the candidate list.

Steve Adamczyk: Hmm, the definition of the term in12.5 [over.built] paragraph 2 is highly ambiguous:

Similarly, the term promoted arithmetic type refers to promoted integral types plus floating types.
I can't tell if that's "promoted integral types plus (all) floatingtypes" or "promoted integral types plus (promoted) floating types".I thought the latter was intended, but indeed the usual arithmeticconversions could give you "float + float", so it makes sense thatfloat would be one of the possibilities. We should discuss this tomake sure everyone has the same interpretation.

Proposed Resolution (October 2003):

Change the second sentence of 13.6 paragraph 2 as follows:

Similarly, the termpromoted arithmetic type referstopromoted integral types plus floating typesfloating types plus promoted integral types.



[8]ページ先頭

©2009-2026 Movatter.jp