在不添加类型转换或删除重载函数的情况下解决重载函数的歧义

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

我做了一个classDummy,它只是原始类型double的包装器。 class 的目的是在我介绍另一个 class 替代 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);
}

报告:

<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)

如果我添加类型转换运算符:

operator double(){
    return content;
}

不知何故它只能在 Visual Studio 下工作,而不是 g++ 9.3.0,这是我的目标编译器。

使用g++9.3.0编译时,报如下错误:

我已经阅读了资料here,不幸的是我无法在这种情况下删除重载函数。我也不能添加类型转换,因为它对我的目的没有意义。

我也查了here,但是我对模板不是很熟悉。因此我的问题是:

我可以在不添加类型转换或删除重载函数的情况下消除 class 中重载函数的歧义吗?

您显示的Dummy class只能转换为long int,但fabs()不接受long int,它接受[=17] =]、doublelong double。由于 long int 可隐式转换为 floatdouble,在您添加 double 转换运算符之前,调用是不明确的。

如果您不想这样做,则必须明确说明要调用 fabs() 的哪个重载。通过:

  • 转换 Dummy 转换的结果:

    double aa = fabs(static_cast<double>(a));
    
  • assigning/casting fabs() 到所需签名的函数指针:

    double (*fabs_ptr)(double) = fabs;
    fabs_ptr(a);
    
    using fabs_ptr = double (*)(double);
    static_cast<fabs_ptr>(fabs)(a);
    

Online Demo