gpt4 book ai didi

c++ - C++ 中代理调用函数的意外歧义

转载 作者:IT老高 更新时间:2023-10-28 21:48:17 26 4
gpt4 key购买 nike

在以下代码中,clang 和 EDG 诊断出不明确的函数调用,而 gcc 和 Visual Studio 接受该代码。

struct s
{
typedef void(*F)();
operator F(); //#1
operator F() const; //#2
};

void test(s& p)
{
p(); //ambiguous function call with clang/EDG; gcc/VS call #1
}

根据 C++ 标准草案 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf) 第 13.3.1.1.2 节 2 说;

a surrogate call function with the unique name call-function and having the form R call-function ( conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1,... ,an); } is also considered as a candidate function.

在上面的代码中,这似乎意味着正在考虑两个调用函数定义(每个转换函数一个),但是两个调用函数具有相同的签名(因此存在歧义),因为转换运算符的 cv 限定符不似乎在调用函数签名中考虑到了。

我希望 #1 会像 gcc 和 Visual Studio 一样被调用。因此,如果 clang/EDG 拒绝上述代码是正确的,有人可以解释一下为什么标准规定在这种情况下应该有歧义以及 代码从代理调用函数的属性中受益?谁是对的:clang(3.5)/EDG(310) 还是 gcc (4.8.2)/VS(2013)?

最佳答案

Clang 和 EDG 是对的。

这是它的工作原理。该标准说(与您的报价相同的来源):

In addition, for each non-explicit conversion function declared in T of the form

operator conversion-type-id () attribute-specifier-seq[opt] cv-qualifier ;

where [various conditions fulfilled in your example], a surrogate call function with the unique name call-function and having the form

R call-function ( conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1, ... ,an); }

is also considered as a candidate function. [do the same for inherited conversions]^128

脚注指出,这可能会产生多个具有无法区分签名的代理,如果这些代理没有被明显更好的候选者取代,则该调用是模棱两可的。

按照这个方案,你的类型有两个转换运算符,产生两个代理:

// for operator F();
void call-function-1(void (*F)()) { return F(); }
// for operator F() const;
void call-function-2(void (*F)()) { return F(); }

您的示例不包含任何其他候选人。

然后编译器执行重载决议。因为这两个调用函数的签名是相同的,所以它将对两者使用相同的转换序列 - 特别是,它将使用转换函数的非常量重载在这两种情况下!所以无法区分这两个函数,调用有歧义。

理解这一点的关键是,在将对象传递给代理项时实际使用的转换不必使用为代理项生成的转换函数!

我可以看到 GCC 和 MSVC 在这里得出错误答案的两种方式。

选项 1 是他们看到两个具有相同签名的代理,然后以某种方式将它们融合为一个。

选项 2 更有可能是他们认为,“嘿,我们不需要在这里为对象进行昂贵的转换搜索,我们已经知道它将使用生成代理的转换函数为了”。这听起来像是一种优化,除了在这种极端情况下,这种假设是错误的。无论如何,通过将转换绑定(bind)到源转换函数,其中一个代理使用 identity-user-identity 作为对象的转换顺序,而另一个使用 const-user-identity,使情况变得更糟。

关于c++ - C++ 中代理调用函数的意外歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22258831/

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