我最近在某个地方(无法记起来)读到了使用大括号允许多个用户定义的转换,但是构造函数转换和转换方法转换之间似乎存在一些我不理解的区别。
考虑:
#include <string>
using ::std::string;
struct C {
C() {}
};
struct A {
A(const string& s) {} // Make std::string convertible to A.
operator C() const { return C(); } // Makes A convertible to C.
};
struct B {
B() {}
B(const A& a) {} // Makes A convertible to B.
};
int main() {
B b;
C c;
// This works.
// Conversion chain (all thru ctors): char* -> string -> A -> B
b = {{"char *"}};
// These two attempts to make the final conversion through A's
// conversion method yield compiler errors.
c = {{"char *"}};
c = {{{"char *"}}};
// On the other hand, this does work (not surprisingly).
c = A{"char *"};
}
现在,我可能误解了编译器的工作,但根据上述和额外的实验,我认为它没有考虑通过转换方法进行的转换。然而,在阅读标准的第4部分和13.3.3.1节时,我找不到原因的线索。这是什么解释呢?
更新
这里有另一个我想要解释的有趣现象。如果我添加
struct D {
void operator<<(const B& b) {}
};
并且在main
函数中:
D d;
d << {{ "char *" }};
我遇到一个错误,但如果我写成d.operator<<({{ "char *" }});
就可以正常工作。
更新2
看起来标准中的第8.5.4节可能会提供一些答案。我会报告我的发现。
A
以使用其operator C
违反了这一点。 - Peterc = A{...
或者c = {A{...
,通过转换方法都可以正常工作。为什么如果我去掉A
,它就决定只使用构造函数呢? - Ari