重载模糊、隐式转换和显式构造函数

11
考虑以下简单程序:
#include <vector>

class A {
  int a;
  int b;

 public:
  explicit A() = default;
  A(int _a, int _b) : a(_a), b(_b) {}

  int f(const A& a) { return 0; }
  int f(std::vector<int> a) { return 1; }
};
int g(const A& a) { return 2; }
int g(std::vector<int> a) {  return 3; }

int main() {
  A a(1,2);
  //   a.f({}); //ambiguous according to gcc
  g({}); //ambiguous according to gcc
  return 0;
}

GCC 10.2拒绝编译它:它说对和的调用是不明确的。Clang编译没有抱怨。
我认为不应该在重载决议中被考虑,因为从无参数的隐式转换是不允许的:标记为显式。
我不确定错误是否属于我,并且无论如何,我都希望找到一种解决方法。
是否有另一个默认生成的构造函数可能是我的问题来源?
您可以在编译器资源管理器上尝试它。

我注意到了这篇 Stack Overflow 帖子。它的答案告诉我们哪个编译器是正确的:是 GCC。但它并没有告诉我们如何使用那些重载规则来获得所需的行为。


@Yakk 完成。寻找一个好的标题总是很困难的。 - AFoley
我会说这是gcc的一个bug,特别是当clang/msvc可以接受它时 演示 - Jarod42
2
有趣的是,如果您注释掉std::vector变量,gcc会抱怨无法使用A的显式构造函数。 - Slava
@MooingDuck 我也不确定我是对的。 - AFoley
1
GCC是正确的 - 请参见dup。 - T.C.
显示剩余5条评论
1个回答

3

你说得对,这似乎是一个bug。下面的被注释掉的代码行由于存在二义性而无法编译。

以下是一个使用std::initializer_list的解决方法:

#include <fmt/core.h>
#include <vector>

class A {
  int a;
  int b;

 public:
  explicit A() = default;
  A(int _a, int _b) : a(_a), b(_b) {fmt::print("Aab\n");}

  void f(const A& a) { fmt::print("A\n"); }
  void f(std::vector<int> a) { fmt::print("vector\n"); }
  void f(std::initializer_list<int> l) {
      return f(std::vector<int>(l));
  }
};
void g(const A& a) { fmt::print("A\n"); }
void g(std::vector<int> a) { fmt::print("vector\n"); }
void g(std::initializer_list<int> a) {return g(std::vector<int>(a)); }

int main() {
  A a(1,2);
  A a2 = A();
  //A a3 = {};
  a.f({});
  g({});
  return 0;
}

谢谢Mark。现在我想我有一个要提交的错误报告。 - AFoley
不错的发现 - 如果您报告了漏洞链接,请分享。我想跟进! - Mark H
最新的编辑显示,似乎这并不是GCC的错误。 - AFoley
好吧,我想我必须向Bjarne认输了! - Mark H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接