c++ - 这是一个clang错误还是我不了解C++的东西?

标签 c++ gcc clang language-lawyer

在查看 this 时问题我用clang试了一下,遇到了一个奇怪的情况。下面的例子:

#include <string>

class ACP
{
public:
    ACP() {}
    operator const std::string() const  { return std::string(); }
    // operator std::string() const  { return std::string(); } <-- makes clang happy
};

void test()
{
   const ACP acp;
   auto a = (std::string)acp;
}

coliru 上编译良好使用 gcc,但使用 clang 失败。至少我认为这个例子没有问题 - 这是 clang 中的一个错误,还是有一个规则可以实际解释 clang 错误并且 gcc 是错误的?

clang 的错误如下所示:

clang -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:13:26: error: no viable conversion from 'const ACP' to 'std::__cxx11::basic_string<char>'
   auto a = (std::string)acp;
                         ^~~
/usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/7.1.0/../../../../include/c++/7.1.0/bits/basic_string.h:421:7: note: candidate constructor not viable: no known conversion from 'const ACP' to 'const std::__cxx11::basic_string<char> &' for 1st argument
      basic_string(const basic_string& __str)
      ^
/usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/7.1.0/../../../../include/c++/7.1.0/bits/basic_string.h:493:7: note: candidate constructor not viable: no known conversion from 'const ACP' to 'const char *' for 1st argument
      basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
      ^
/usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/7.1.0/../../../../include/c++/7.1.0/bits/basic_string.h:515:7: note: candidate constructor not viable: no known conversion from 'const ACP' to 'std::__cxx11::basic_string<char> &&' for 1st argument
      basic_string(basic_string&& __str) noexcept
      ^
/usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/7.1.0/../../../../include/c++/7.1.0/bits/basic_string.h:542:7: note: candidate constructor not viable: no known conversion from 'const ACP' to 'initializer_list<char>' for 1st argument
      basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc())
      ^
main.cpp:7:5: note: candidate function
    operator const std::string() const  { return std::string(); }
    ^
/usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/7.1.0/../../../../include/c++/7.1.0/bits/basic_string.h:515:35: note: passing argument to parameter '__str' here
      basic_string(basic_string&& __str) noexcept
                                  ^
1 error generated.

但是我不明白为什么编译器不能使用来自 std::string 的复制 ctor。

最佳答案

简化:

struct A {};
struct B { operator const A(); };
B b;
A a(b);

这是direct-initializationdestination type class type A,所以 candidate constructors枚举 A 的所有构造函数,选择 A 的所有构造函数(包括隐式定义的复制和移动构造函数)并通过 overload resolution 进行比较对于 direct-initialization of a class object .首先对构造函数进行评估 viability ,这意味着试图构造一个 implicit conversion sequenceb(一个左值 B)到它们的参数。由于参数是一个引用(A const&A&&),我们必须执行 reference initialization .我们可以initialize a reference A const& 来自 b 因为 b 可以转换为右值 A constA const(目标引用的类型)和A const(目标函数的返回类型)是reference-compatible (因为它们是相同的 cv 限定类型);确实,这是一个 direct reference binding .我们无法从 b 初始化引用 A&&,因为 A&& has lesser cv-qualification一个 const。所以 A::A(A const&) 是唯一可行的构造函数并被选中。

这已被多次报告为 clang 1 2 3但遗憾的是没有被接走。

所有其他主要编译器(gcc、ICC、MSVC)都能正确编译代码。

有趣的是,正如所讨论的 here clang 在 C++03 模式下正确编译代码。如果我们通过抑制其移动构造函数来强制 A 成为“C++03 风格”类型,clang 将编译生成的代码:

struct A { A(A const&) = default; };
struct B { operator const A(); };
B b;
A a(b);

这表明可能 clang 被移动构造函数弄糊涂了。它不应该,因为移动构造函数不可行; A&& a = b; 无效。

关于c++ - 这是一个clang错误还是我不了解C++的东西?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45455741/

相关文章:

c++ - C++ 可以编译成平台独立代码吗?为什么不?

c++ - 在析构函数中调用观察者是不好的做法吗?

c++ - Protocol Buffer 在解析时是否重用字符串指针?

c++ - 简而言之,GCC 选项 -fipa-pta 的作用是什么?

c++ - ld : symbol(s) not found for architecture x86_64 using GNU Make and clang

c++ - 在禁用所有编译器优化的情况下使用 volatile

c - 使用 GCC 时 OpenMP 没有进行实际的并行处理

c++ - 成员函数参数的类型

c++ - 分配给数组成员时 Clang 中的 "Read-only variable is not assignable"

c++ - 为什么 GCC 在 Clang 不使用它的地方插入 mfence?