重载函数以与变量和文字一起使用 - 模棱两可的调用错误

问题描述 投票:0回答:1

我正在尝试重载一些函数以处理多种数据类型。当我将变量作为参数传递时,这是微不足道的,因此:

void fnc(int32_t d){
  Serial.println((String) "int32 = " + d);
}
void fnc(char* d){
    Serial.println((String) "string = " + d);
}

void fnc(bool d){
  if(d){ Serial.println((String) "bool = " + "true"); }
  else{ Serial.println((String) "bool = " + "false"); }
}

void fnc(float d){
  Serial.println((String) "float = " + d);
}

int32_t anInt = 29339222;
char* aStr = "baloney";
bool aBool = false;
float aFloat = 3.1415;

void setup() {
  Serial.begin(9600);
  fnc(anInt);
  fnc(aStr);
  fnc(aBool);
  fnc(aFloat);
}

(注意,这是在 Arduino 上,因此使用 setup() 而不是 main()。)

结果如您所料:

int32 = 29339222

串 = 胡说八道

布尔 = 假

浮动 = 3.14

现在,我需要传递文字值和变量,如下所示:

  fnc(8728787);
  fnc("spamoney");
  fnc(true);
  fnc(2.718);

编译器抱怨最后一行调用 fnc(2.718):

sketch_apr1a.ino:34:12: error: call of overloaded 'fnc(double)' is ambiguous
   fnc(2.718);

我想这是因为作为文字,参数没有为编译器提供类型信息。该值的实际位可以解释为任何 4 字节类型(Arduino 上的 float 是 4 字节)而 int32_t 是 4 字节类型。

所以,有几个问题:

  1. 为什么编译器没有出现类似8728787作为参数的问题?那应该同样模棱两可,不是吗?
  2. 我怎样才能使这项工作?有没有办法接受所有这些类型作为变量和文字?

注意:我不想使用模板函数,因为我需要用不同的算法处理不同的类型。

注意:我现在已经通过简单地创建多个函数(即 fncInt、fncStr、fncBool 等)解决了这个问题。这可行,但是......它以错误的方式摩擦我的强迫症。

注意注意:这将是图书馆的一部分。我还想避免强迫使用它的人执行 fnc((float) 2.718) ,原因与上一条注释相同。也许这很愚蠢。我不知道。

c++ arduino overloading literals ambiguous-call
1个回答
1
投票

您的问题是文字

2.718
的类型是
double
,而不是
float
。 C++ 在执行重载决策时最多允许一个内置转换和一个用户定义的转换,因此需要一个转换来匹配
fnc
的任何重载,因为没有
fnc(double)
重载。有从
double
int32_t
bool
float
的内置转换,编译器认为它们都不比其他任何一个“更好”,因为它们都是有损转换。因此这个调用是不明确的,因为它不知道你是想调用
fnc(int32_t)
fnc(bool)
还是
fnc(float)

如果您让浮点重载接受

double
而不是浮点数,则会出现精确匹配, 被认为比需要转换的匹配“更好”,因此会选择它。

还要注意,

float
double
的转换也被认为比其他提到的“更好”,因为它是无损的,而其他的是有损的,所以对于调用
fnc(aFloat)
编译器也会选择
fnc(double)
而不是其他选项。

或者,您可以将

f
后缀附加到您的浮点文字,以明确使其成为
float
。例如
fnc(2.718f)
是没有歧义的。


  1. 为什么编译器没有出现类似8728787作为参数的问题?那应该同样模棱两可,不是吗?

这个有点复杂。在 Arduino 上,

int
可以是 16 位或 32 位,具体取决于具体的电路板。

  • 文字
    8728787
    的类型将是
    int
    (如果
    int
    是 32 位)或
    long int
    (如果
    int
    是 16 位),因为
    8728787
    太大而无法表示16 位。
  • int32_t
    将是
    int
    (如果
    int
    是 32 位)或
    long int
    (如果
    int
    是 16 位)的别名。

无论哪种情况,

8728787
的类型都将与
int32_t
完全匹配。由于它是完全匹配,所以
fnc(int32_t)
将被选中而不是其他选项。

如果您尝试将 64 位整数传递给

fnc
,您将得到与
double
float
情况相同的歧义。例如,由于与
double
调用相同的原因,以下内容是不明确的:

int64_t aLongInt = 123;
fnc(aLongInt);
© www.soinside.com 2019 - 2024. All rights reserved.