当前位置: 首页 > 知识库问答 >
问题:

重载运算符在Clang上有歧义,但在GCC上没有,哪一个是正确的?

谷梁嘉悦
2023-03-14
#include <iostream>


template <typename T>
struct Wrapper {
    operator T const &() const & {
        std::cout << "Wrapper::operator T const &() const &\n";
        return _obj;
    }

    operator T&() & {
        std::cout << "Wrapper::operator T&() &\n";
        return _obj;
    }

    operator T&&() && {
        std::cout << "Wrapper::operator T&&() &&\n";
        return std::move(_obj);
    }

private:
    T _obj;
};

struct Test {
    Test& operator=(Test const &test) {
        std::cout << "Test& Test::operator=(Test const &)\n";
        return *this;
    }

    Test& operator=(Test &&test) {
        std::cout << "Test& Test::operator=(Test &&)\n";
        return *this;
    }
};

int main() {
    Test test;
    Wrapper<Test> wrapperTest;

    test = wrapperTest;               // OK for all
    test = std::move(wrapperTest);    // OK for GCC and ICC, not for Clang and VC++

    return 0;
}

VC:

(34):错误C2593:'运算符='是含糊不清的

(26):注意:可能是测试

(25):注:或“测试”

(69):注意:当试图匹配参数列表时'(测试,包装器)'

======生成:0成功,1失败,0最新,0跳过==========

叮当声:

: 34:7:错误:重载运算符=的使用不明确(操作数类型为Test和typename std::remove_reference

测试=标准::移动(包装测试);//适用于GCC和ICC,不适用于Clang和Microsoft Visual C

~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~

:25:8:注:候选函数

测试

^

:26:8:注:候选函数

测试

^

产生1个错误。

共有1个答案

上官高逸
2023-03-14

我认为gcc和icc是正确的。

test = std::move(wrapperTest);

分配一个包装器

从价值类别:

当用作函数参数且函数有两个重载可用时,一个重载使用右值引用参数,另一个重载使用左值引用常量参数,rvalue绑定到rvalue引用重载(因此,如果copy和move构造函数都可用,则rvalue参数将调用move构造函数,同样,还会调用copy和move赋值运算符)。

和非静态成员函数:

非静态成员函数可以使用左值ref限定符(标记)或

现在,我们有这些候选人:

  • 测试

基于这些段落,编译器应该选择Test

 类似资料:
  • 我有带转换操作符的简单代码,似乎所有的编译器都给出不同的结果,我很好奇哪个编译器是正确的?我也尝试了不同的组合,但以下是最有趣的。代码是使用C 11标志编译的,但是在C 03中也可能观察到相同的行为。 叮当声-3.6: g -4.9: msvc 2014年CTP: 删除后: msvc编译: 此外,在移除const in后 叮当声-3.6: g -4.9: msvc 2014年CTP:

  • 我试图移植一些为GCC(8.2)编写的代码以供Clang编译: GCC 8.2(和12.1)很好地编译了代码。然而,Clang 11.0.0(和14.0.0)抱怨说,从fe到feh的调用在无效feh之间不明确(Fn https://godbolt.org/z/5E9M6a5c6 哪个编译器是正确的? 如何编写这段代码以便两个编译器都接受它? 这两个和折叠表达式都可以在C 17中使用,但这是许多项目

  • 假设我们有以下简单的代码: 这段代码使用clang编译并打印“T”,但使用gcc我们有以下错误: 我的问题是哪个编译器有bug,gcc还是叮当声?

  • 前面章节介绍了 Python 中的各个序列类型,每个类型都有其独特的操作方法,例如列表类型支持直接做加法操作实现添加元素的功能,字符串类型支持直接做加法实现字符串的拼接功能,也就是说,同样的运算符对于不同序列类型的意义是不一样的,这是怎么做到的呢? 其实在 Python 内部,每种序列类型都是 Python 的一个类,例如列表是 list 类,字典是 dict 类等,这些序列类的内部使用了一个叫作

  • 运行此代码时,Clang(3.9.1)和GCC(7,快照)将“1”、“2”打印到控制台。 但是,MSVC未能编译此代码: source_file.cpp(15):错误C2668:字典::集:对重载函数的模糊调用 source_file.cpp(9):注意:可能是“无效字典::集(int64_t)” source_file.cpp(8):注意:或'无效字典::集(const char*)' 源文件。

  • 我有一个MCVE,它在我的一些机器上使用g版本4.4.7编译时崩溃,但确实适用于clang版本3.4.2和g版本6.3。 我想知道它是来自未定义的行为还是来自这个古老版本的gcc的实际错误。 这实际上是最小的,如果删除此代码的任何功能,它就会正确运行。 当使用编译时,代码片段可以正常工作,但是对于GnuCC上定义的的每个标志,使用编译时仍然可以正常工作留档。 生成核心转储,可以从中提取回溯: 请随