c++ - 模棱两可的重载、隐式转换和显式构造函数
问题描述
考虑以下小程序:
#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 拒绝编译它:它说调用g({})
并且a.f({})
是模棱两可的。Clang 编译这个没有抱怨。
在我看来,g(const A&)
不应该在重载决议中考虑,因为不允许从无参数进行隐式转换:A::A()
被标记为显式。
我不确定错误不是我的,无论如何,我想找到一个解决方法。
是否有另一个默认生成的构造函数可能是我的问题的根源?
您可以在编译器资源管理器上尝试。
这篇SO 帖子引起了我的注意。它的答案告诉我们哪个编译器是正确的:它是 GCC。但它并没有告诉我们如何使用这些重载规则获得所需的行为。
解决方案
你是对的,它看起来像一个错误。下面注释掉的行由于不应该有歧义的确切原因而无法编译。
使用 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;
}
推荐阅读
- javascript - 如何在每个刷新页面上重置整数计数器
- java - buildSessionFactory 在junit测试模式下抛出“网络适配器无法建立连接”错误,这在实时模式下很好
- mongodb - 插入多个文档时出现 MongoDB 错误
- h2o - H2O 在 lambda 函数中抛出 Unexpected bytecode disassembly @ " + str(s) 错误
- javascript - HostListener 的单元测试角度
- flutter - 如何对加载的 FirebaseAnimatedList 进行排序?
- powershell - 如何将 foreach 循环的结果通过管道传输到输出文件?
- swift - 如何将动态框架正确放入 Xcode12.5
- javascript - 单击此按钮时如何从按钮中删除轮廓边框?
- android - 片段返回导航,无需再次从网络获取数据