整数参数调用浮点重载,浮点参数调用整数重载?

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

今天我遇到了大致以下代码:

#include <iostream>

void f(float&& f) { std::cout << f << "f "; }
void f(int&& i) { std::cout << i << "i "; }

int main()
{
    int iv = 2; float fv = 1.0f;
    f(2);  f(1.0f);
    f(iv); f(fv);
}

神箭链接

前两个 f 调用打印

2i 1f
,如预期。

现在对于第二行,我预计它要么根本不编译,因为 iv 和 fv 不是临时变量(因此不能绑定到 r 值引用),或者它创建变量的副本传递给函数,然后再次打印

2i 1f

但是,不知怎的,它打印了

2f 1i
,这几乎是我最不想看到的事情。

如果将代码复制到 cppinsights 中,它会将调用转换为

f(static_cast<float>(iv));
f(static_cast<int>(fv));

所以它看起来非常有意地将整数转换为浮点数,然后将浮点数转换为整数,但我不知道为什么这样做,而且也不知道如何谷歌。为什么会出现这种情况?导致这个结果的规则是什么?

c++ overloading
3个回答
1
投票

为了避免考虑隐式转换,请像这样重写代码。使用 C++17 语法(因为您在 godbolt 链接中使用了该语法) 至少现在有问题的代码不会编译。

通过显式约束,类型必须完全匹配,并且不考虑隐式转换。 (C++20 语法会更好一点)

演示:https://godbolt.org/z/MexsGT55T

#include <iostream>
#include <type_traits>

template<typename type_t>
auto f(type_t&& f) -> std::enable_if_t<std::is_same_v<type_t,float>,void>
{ 
    std::cout << f << "f "; 

}

template<typename type_t>
auto f(type_t&& f) -> std::enable_if_t<std::is_same_v<type_t,int>,void>
{ 
    std::cout << f << "f "; 

}

int main()
{
    int iv = 2;
    float fv = 1.0f;

    f(2);  f(1.0f);
    f(iv); f(fv); // <== will no longer compile now
}

0
投票

为了避免隐式转换,请提供一个删除函数模板,如果非模板化重载不完全适合,则选择该模板。也就是说,只需添加这个重载:

template<typename T>
void f(T&&) = delete;

0
投票

程序的行为可以从引用初始化来理解。

来自 dcl.init#ref-5.4

【例6:

double d2 = 1.0;
double&& rrd2 = d2;                 // error: initializer is lvalue of related type
int i3 = 2;
double&& rrd3 = i3;                 // rrd3 refers to temporary with value 2.0

-结束示例]


案例1

这里我们讨论为什么调用

void f(int&& i)
对于调用
f(iv)
不可行。

左值

iv
无法绑定到
i
中的右值引用参数
void f(int&& i)
,因此对于调用
f(iv)
,重载
f(int&&)
不是可行。基本上,
int&& i = iv;
是不允许的,因为
iv
是相关类型的左值。


案例2

但是对于调用

f(iv)
,第一个重载(
void f(float&& f)
)是可行的(并且匹配),因为/通过临时物化。该标准甚至有具体的示例,如您的情况。

© www.soinside.com 2019 - 2024. All rights reserved.