How to diagnose ambiguous call to sqrt(int&) in g++ 4.3.4
Asked Answered
W

2

8

My code is as follows:

#include <cmath>
#include <iostream>

float foo(float f) {
    std::cout << "float\n";
    return f;
}
double foo(double d) {
    std::cout << "double\n";
    return d;
}

int main() {
    int i = 16;
//  foo(i); // ambiguous call, of course
    return (int) std::sqrt(i);
}

The call in the last line is not reported ambiguous even with -pedantic -std=c++98 -Wall -Wextra, but it doesn't necessarily work at all in other compilers, for the same reason foo(i) doesn't.

gcc adds the following to namespace std:

template<typename _Tp>
    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
                                       double>::__type
    sqrt(_Tp __x)
    { return __builtin_sqrt(__x); }

That is, it adds inline double sqrt(X) for all integer types X.

I appreciate g++ doing its best to help me out and all, but is there any (legitimate) way to make it diagnose the bug in my code?

[Edit: I'm using gcc 4.3.4, but if other versions of gcc can diagnose it then I'm interested in that fact too!]

Wraith answered 19/5, 2011 at 9:12 Comment(5)
Are you saying the standard says the behaviour should be undefined, or that it is implementation defined? Do you have a reference on that to add to the question?Intrusion
I believe that it conforms to the standard for gcc to add extra sqrt overloads to namespace std, although I haven't checked the standard for a reference. I'm not trying to claim that gcc is buggy, just that I'd prefer it to behave differently if possible.Wraith
I believed wrong, turns out implementations can't add new signatures to existing functions.Wraith
@Steve: sorry, my fault. I just wanted to get rid of the "overloads" tag, when "overloading" was already widely used. My Java background got the better of me here ;-)Minaret
@Joachim: fair enough. My thinking at the time was that my question was about the overloads of std::sqrt, but using the existing tag is definitely better. I should watch out for that, the power to create tags means I did so entirely by accident...Wraith
W
2

This "helpful" Standard Library addition by GCC is non-conforming in C++03, according to
[lib.global.functions]/2:

A call to a global function signature [described in the Standard Library definition] behaves the same as if the implementation declares no additional global function signatures.

Which means that the implementation (gcc) is not permitted to add extra overloads (helpful or not), as long as they affect the observable behavior of the program.

Woodwaxen answered 19/5, 2011 at 9:48 Comment(0)
K
2

You want the quote from the FDIS?

Last paragraph of 26.8:

Moreover, there shall be additional overloads sufficient to ensure:

  1. If any argument corresponding to a double parameter has type long double, then all arguments corresponding to double parameters are effectively cast to long double.

  2. Otherwise, if any argument corresponding to a double parameter has type double or an integer type, then all arguments corresponding to double parameters are effectively cast to double.

  3. Otherwise, all arguments corresponding to double parameters are effectively cast to float.

In this case it must be point 2 that applies.

Koine answered 19/5, 2011 at 9:31 Comment(4)
That paragraph isn't present in C++03. There is a corresponding paragraph in C99 in the description of <tgmath.h>. So my current opinion is that g++ behavior is in fact mandated in C++0X but probably not valid in C++03.Chenay
OK, so that makes sense. A bug in gcc's future support for C++0x has made it leak back in time to C++03 (or c++98 as gcc refers to it).Wraith
@Steve - Considering that C has a double sqrt(double) that would be called for an int parameter, it could also be considered a bug in C++98. Is an implementation allowed to fix bugs in the standard? :-)Koine
I don't see that it's a bug in C++03, just an incompatibility between C++03 and C99. And apparently an incompatibility between C++03 and GCC.Wraith
W
2

This "helpful" Standard Library addition by GCC is non-conforming in C++03, according to
[lib.global.functions]/2:

A call to a global function signature [described in the Standard Library definition] behaves the same as if the implementation declares no additional global function signatures.

Which means that the implementation (gcc) is not permitted to add extra overloads (helpful or not), as long as they affect the observable behavior of the program.

Woodwaxen answered 19/5, 2011 at 9:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.