gpt4 book ai didi

C++ 函数重载中的模糊调用

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:35:51 24 4
gpt4 key购买 nike

只是出于好奇(学术问题:P),请考虑以下代码:

struct Y {};

class PassConstY {
public:
PassConstY(const Y& y) {}
};

class PassY {
public:
PassY(Y& y) {}
};

void z(PassConstY y) {}
void z(PassY y) {}

void h(const Y& y) {}
void h(Y& y) {}

Y y;
const Y cy;
h(cy); //OK
h(y); //OK
z(cy); //OK
z(y); //Ambiguity

问题:是否可以编写PassYPassConstY s.t.

  1. zh 遵循完全相同的重载规则
  2. 如果我删除可变 Yzh 定义,代码仍然可以编译(即我可以调用 zh 也是可变版本)。

我的猜测是否定的,因为我设法让 PassConstY 只能从 const Y 构造(而不是可变的 Y ),这消除了歧义,但第 2 点注定要失败。


说明:

PassY 和 PassConstY 可以随意定义(但必须是类,可以模板化),但 z 和 h 的定义必须不变。

只有定义了 z 和 h 的“常量”版本时,才能编译以下代码:

const Y y;
z(y); //Calls z(PassConstY y)
h(y); //Calls h(const Y& y)

Y x;
z(x); //Calls z(PassConstY y)
h(x); //Calls h(const Y& y)

只有定义了 z 和 h 的“可变”版本时,才能编译以下代码:

Y x;
z(x); //Calls z(PassY y)
h(x); //Calls h(Y& y)

当 h 和 z 的两个版本都被定义时,下面的代码必须编译:

const Y y;
z(y); //Calls z(PassConstY y)
h(y); //Calls h(const Y& y)

Y x;
z(x); //Calls z(PassY y)
h(x); //Calls h(Y& y)

抱歉,如果原来的问题不够清楚!


动机(真的是我在 Stackoverflow 上的另一个问题):

关于下面评论中的“禁用 r 值绑定(bind)”,我想提出一个模板类 Ref(将其视为智能引用),我可以在编写函数定义时使用它,例如:

struct X {};

void f(Ref<X> x) {} //Instead of void f(X& x)
void f(Ref<const X> x) {} //Instead of void f(const X& x)

这样我在调用函数 f 时(就重载解析/转换而言)得到与普通引用版本相同的行为,但 Ref 从不绑定(bind)到右值。

[这部分需要C++0X]

最佳答案

这样做的原因是:

  • 如果 SCS 1 绑定(bind)对 const 的引用,而 SCS 2 绑定(bind)对非 const 的引用,则 SCS 1 优于 SCS 2。
  • UCS 1 优于 UCS 2 当且仅当两者都使用相同转换函数或构造函数。

对于使用 SCS 的 h,第一个项目符号将找出两个函数都是可行候选者(第二次调用)的情况的获胜者。对于 z,在两个函数都是可行候选者(第二次调用)的情况下,没有比另一个 UCS 更好的 UCS,因为两个 UCS 使用不同的构造函数。

注意 UCS 定义为

  • 一个 SCS(在使用构造函数的情况下将参数转换为构造函数的参数类型,并为转换运算符函数转换为 TypeOf(*this) &)
  • 调用用户定义的转换(构造函数或转换运算符函数)
  • 另一个 SCS(将转换结果转换为最终目标类型)。

您不能为“const Y to Y&”形成一个 SCS,因此第二个 h 函数的 UCS 不存在第一个 SCS,因此它不是一个可行的候选者。但是,第二次调用 h 时情况并非如此,因此会导致上述歧义。


我缩短了一些术语:

UCS:用户定义的转换序列
SCS:标准转换序列


My guess is no, in the sense that I managed to have PassConstY constructable from a const Y only (and not a mutable Y), which removes the ambiguity, but then point 2 is doomed to failure.

如果我没理解错的话,你的怀疑是不正确的。使用您当前的定义,您可以删除hz 的可变版本,并且您的代码可以正常编译。有 Yconst Y& 的 SCS。


当然,您可以将 PassY 和 PassConstY 重写为

typedef Y &PassY;
typedef Y const& PassConstY;

除此之外,当您说“重写”时,我不确定您指的是什么。如果您只想更改类主体,那么重载解析肯定会有所不同。

关于C++ 函数重载中的模糊调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4680389/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com