C++ 这是一只叮当作响的虫子还是我不知道的东西';我不知道C++;?
在看问题的时候,我用叮当声试了一下,结果陷入了一个奇怪的境地。下面是一个例子:C++ 这是一只叮当作响的虫子还是我不知道的东西';我不知道C++;?,c++,gcc,clang,language-lawyer,C++,Gcc,Clang,Language Lawyer,在看问题的时候,我用叮当声试了一下,结果陷入了一个奇怪的境地。下面是一个例子: #include <string> class ACP { public: ACP() {} operator const std::string() const { return std::string(); } // operator std::string() const { return std::string(); } <-- makes clang happ
#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;
}
#包括
类机场核心计划
{
公众:
ACP(){}
运算符const std::string()const{return std::string();}
//运算符std::string()常量{return std::string();}简化:
struct A {};
struct B { operator const A(); };
B b;
A a(b);
这与A
有关,因此将枚举A
,选择A的所有构造函数(包括隐式定义的复制和移动构造函数)并与for进行比较。首先对构造函数进行评估,这意味着尝试从b
构造一个(左值b
)由于参数是一个引用(a const&
或a&
),我们必须执行a。我们可以a const&
从b
,因为b
可以转换为右值a const
,以及a const
(目标引用的类型)和a const
(目标函数的返回类型)是(因为它们是相同的cv限定类型);事实上,这是a。我们无法从b
初始化引用a&&
,因为a&&
比a常量
。因此a::a(a常量&)
是唯一可行的构造函数,并且被选中
这已被报告叮当声多次,但不幸的是,还没有被发现
所有其他主要编译器(gcc、ICC、MSVC)正确编译代码
有趣的是,如前所述,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;
无效。clang看起来有点可疑,但返回const对象可能是逻辑错误或您的误解。您确定不想返回referee吗nce到const string?std::string a=acp;
而不是auto a=(std::string)acp;
在任何方面都有帮助的情况下工作。实际上,只需在操作符前面添加explicit
也会让clang高兴…显式操作符const std::string()const{return std::string();}
当只允许一个转换时,这不是要求两个隐式的用户定义转换吗?第一个转换ACP->const std::string
,第二个转换const std::string->std::string
(通过复制构造函数)@richardhoges返回const
对象而不是非const is(was)实际上是Scott Meyer推荐的一种做法,至少对C++03是这样(如果我没记错的话)。
struct A { A(A const&) = default; };
struct B { operator const A(); };
B b;
A a(b);