【发布时间】:2014-04-11 02:47:26
【问题描述】:
在以下代码中,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 说;
具有唯一名称 call-function 并具有 R call-function (conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1,... ,一个); } 也被视为候选函数。
在上面的代码中,这似乎意味着正在考虑两个调用函数定义(每个转换函数一个),但是两个调用函数具有相同的签名(因此存在歧义),因为转换运算符的 cv 限定符不似乎在调用函数签名中考虑到了。
我希望 #1 会像 gcc 和 Visual Studio 一样被调用。因此,如果 clang/EDG 拒绝上述代码是正确的,那么有人可以解释一下为什么标准规定在这种情况下应该有歧义以及 代码从代理调用函数的属性中受益?谁是对的:clang(3.5)/EDG(310) 还是 gcc (4.8.2)/VS(2013)?
【问题讨论】:
-
问题似乎仅限于代理调用函数的重载解决方案;在解析
void foo( void(*)() ); foo(p);时,clang++ 明确选择第一个转换函数:live example(考虑到 [over.call.object]/4,这很奇怪。) -
你用的是哪个版本的gcc?从 gcc46 升级到 gcc47 后,我遇到了一个相关问题,这种情况与您的情况类似,但在先前编译的重载模板函数上导致错误,直到我重命名其中一个。升级后我还有更多需要解决的警告。
-
@andrew-mcdonnell 它是 gcc 4.8.2。我还编辑了问题以包含我尝试过的其他编译器的版本号。
-
非常类似于stackoverflow.com/q/22064519/476681。我认为 gcc 和 msvc 是正确的。
标签: c++ gcc clang language-lawyer