gpt4 book ai didi

c++ - 通过引入不相关的调用运算符奇怪地解决了模棱两可的调用运算符重载 - clang vs gcc

转载 作者:行者123 更新时间:2023-12-04 16:38:04 24 4
gpt4 key购买 nike

考虑实现 overload_two 类的任务,以便编译以下代码:

int main()
{
overload_two o{
[](int) { return 1; },
[](char){ return 2; }
};

static_assert(o(0) + o('a') == 3);
}

第一次尝试看起来像这样:

template <typename F, typename G>
struct overload_two : F, G
{
overload_two(F f, G g) : F{f}, G{g} { }
};

当然,这会失败并出现以下错误 (gcc 11.0.1):

<source>:15:22: error: request for member 'operator()' is ambiguous
15 | static_assert(o(0) + o('a') == 3);
| ^

<source>:12:9: note: candidates are: 'main()::<lambda(char)>'
12 | [](char){ return 2; }
| ^

<source>:11:9: note: 'main()::<lambda(int)>'
11 | [](int) { return 1; },
| ^

预期的解决方案是通过 using 声明将 F::operator()G::operator() 纳入范围。然而 - 非常令人惊讶 - 引入一个看似无关的 operator() 也有效:

template <typename F, typename G>
struct overload_two : F, G
{
overload_two(F f, G g) : F{f}, G{g} { }
auto operator()(F&) { } // wtf?
};

live example on godbolt.org


此外,clang 13.0.0 似乎在没有 using 声明或随机 operator() 的情况下也能正常工作:live example on godbolt.org .


我的问题是:

  1. 在没有任何 operator()using 声明的情况下,gcc 拒绝执行 overload_two 是否正确?

  2. gcc 接受带有 operator()(F&) 且没有 using 声明的 overload_two 的实现是否正确?

  3. clang 在没有任何 operator()using 声明的情况下接受 overload_two 的实现是否正确?

最佳答案

  1. 是的。名称 operator() 的名称查找是不明确的,因为它在两个基中都找到了名称(参见 [class.member.lookup]/5.2 )。这是一个错误,不要通过 GO,不要收取 200 美元。
  2. 是的。不相关的 operator() 通过隐藏基类成员使名称查找成功。因为您的 lambda 是无捕获的,所以它们可以隐式转换为函数指针,并且这些隐式转换由派生类继承。当您的类可转换为函数指针(或引用)时,重载解析将另外生成 surrogate call functions从这些转换。这些将被选择用于示例中的调用。
  3. 没有。参见 #1。

关于c++ - 通过引入不相关的调用运算符奇怪地解决了模棱两可的调用运算符重载 - clang vs gcc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66767828/

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