gpt4 book ai didi

c++ - 不同编译器的重载分辨率不同

转载 作者:行者123 更新时间:2023-12-01 12:32:57 24 4
gpt4 key购买 nike

我已经构建了我的问题的以下最小示例:

#include <iostream>

struct Foo {
Foo() {
std::cout << "default" << std::endl;
}
Foo(Foo& f2) {
std::cout << "non-const" << std::endl;
}
Foo(const Foo& f2) {
std::cout << "const" << std::endl;
}
};

int main() {
std::pair<Foo, int> foop0(Foo(), 1);
std::cout << std::endl;
std::pair<const Foo, int>foop1(foop0);
}

在我的 Ubuntu 机器上 g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 将打印出以下内容:
$ g++ -std=c++14 test.cpp -o test && ./test
default
const

const

但是,Apple clang(版本 11.0.3 (clang-1103.0.32.62)
目标:x86_64-apple-darwin19.4.0) 在我的 Mac 上将打印:
$ g++ -std=c++14 test.cpp -o test && ./test
default
const

non-const

但是,情况变得更糟:如果我将最后一行更改为
std::pair<Foo, int>foop1(foop0);
^ removed const

两个编译器都会给出第一个输出。

为什么会发生这种情况?

编辑:根据 cppreference,我现在明白为什么了,std::pair 的 ctors 应该像 g++ 一样被选择。这里仍然没有解释 clang 的怪异行为。可能是不符合标准的实现?

最佳答案

如前所述,可能是 std::pair 的实现因为两者不同。我写了两个非常相似的对的实现,即使没有改变对的类型,它们也能完全展示你不同的行为:godbolt

#include <iostream>

struct T {
T() {
std::cerr << "default\n";
}

T(T&) {
std::cerr << "non-const\n";
}

T(const T&) {
std::cerr << "const\n";
}

};

// Comment or uncomment to change the behavior.
//#define MAC

template<class First, class Second>
struct pair {
First first;
Second second;

pair(const First& f, const Second& s) : first(f), second(s) {
}

#ifdef MAC

pair(pair<First, Second>& p) : first(p.first), second(p.second) {
std::cerr << "copy Mac-Like\n";
}

#else

pair( pair<First, Second>& p) : pair(p.first, p.second) {
std::cerr << "copy Ubuntu-Like\n";
}
#endif

};

int main() {
T t;
pair<T, int> u1(t, 0);

pair<T, int> u2(u1);
}

当然,mac 和 ubuntu 上的对都写得更合理(并且符合标准),并且标准复制构造函数采用 const 引用(这就是他们当时都使用 const 变体的原因)。但是我猜他们会以不同的方式处理来自具有不同但可转换类型的对的复制构造函数。找出究竟有什么不同需要比较两个系统上的 STL 实现。

Ubuntu 变体对我来说似乎很清楚,这对只是通过构造函数中的 const 引用从一对可转换类型中获取。当你在构造链的任何一点有一个 const 时,你最终会得到 T 的 const 复制构造函数。 .

我发现 Mac 的行为有点奇怪,因为它们必须通过值或非常量引用来获取对(实际上,您不应该通过非常量引用获取复制构造函数,为什么要改变它呢?拷贝?这似乎是 std::auto_ptr 级别的怪异)。也许他们(试图)聪明地处理了某种“按值(value)取而代之”的事情。

但我认为这是不合格的,因为 pair constructor应该通过常量引用或右值引用来获取所有其他对。由于我们正在复制,它应该使用复制构造函数,接受一个 const 引用,因此也有一个对 pair.first 的 const 引用。并通过它的 const 复制构造函数。

关于c++ - 不同编译器的重载分辨率不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62123033/

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