c++castingambiguity

To solve ambiguity of overloaded function without either adding typecasting or remove the overloaded functions


I made a class Dummy, which is just a wrapper of primitive type double. The purpose of the class is to test potential problems before I introduce another class that substitutes the double class.

Dummy.h:

class Dummy{
private:
    double content;
public:
    Dummy(double _content) :content{ _content } {};
    operator long int()  {return (long int)content;};
}

test.cpp:

#include <math.h>

int main(){
    Dummy a = Dummy(1.1);
    double aa = fabs(a);
}

It reports:

<source>:17:27: error: call of overloaded 'fabs(Dummy&)' is ambiguous 
   17 |     std::cout << std::fabs(foo);
      |                  ~~~~~~~~~^~~~~ In file included from /usr/include/features.h:461,
                 from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/x86_64-linux-gnu/bits/os_defines.h:39,
                 from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/x86_64-linux-gnu/bits/c++config.h:586,
                 from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/cmath:41,
                 from <source>:1: /usr/include/x86_64-linux-gnu/bits/mathcalls.h:162:1: note: candidate:
'double fabs(double)'
  162 | __MATHCALLX (fabs,, (_Mdouble_ __x),
(__const__));
      | ^~~~~~~~~~~ In file included from <source>:1: /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/cmath:241:3:
note: candidate: 'constexpr float std::fabs(float)'
  241 |  
fabs(float __x)
      |   ^~~~ /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/cmath:245:3:
note: candidate: 'constexpr long double std::fabs(long double)'
  245 |   fabs(long double __x)

If I add a type conversion operator:

operator double(){
    return content;
}

It somehow only works under Visual Studio, not g++ 9.3.0, which is my target compiler.

During the compiling with g++ 9.3.0, the following errors are reported:

Error Message from g++

I have read the information here, unfortunately I can't remove the overloaded functions in this case. Neither can I add typecasting, because it doesn't make sense for my purpose.

I also check here, but I am not so familiar with templates. Hence my question is:

Can I eliminate the ambiguity of overloaded function within the class, without adding typecasting, or removing the overloaded functions?


Solution

  • The Dummy class you have shown is only convertible to long int, but fabs() does not accept long int, it accepts either float, double, or long double. Since long int is implicitly convertible to float and double, the call was ambiguous until you added the double conversion operator.

    If you don't want to do that, then you have to be explicit about which overload of fabs() you want to call. Either by:

    Online Demo