问题
I have the following code, which constructs one object t2 using a explicit conversion constructor, which performs an implicit conversion of t1. This is expected, and is described in The C++ Programming Language, in section 11.4.1 of the 3rd edition.
#include <iostream>
#include <string>
using namespace std;
class test1 {
public:
test1() {}
operator string() {
cout << "test1 string conversion operator called" << endl;
return string();
}
};
class test2 {
public:
test2() {}
test2(string s) {
cout << "test2 string conversion constructor called" << endl;
}
};
int main() {
test1 t1;
test2 t2(t1);
return 0;
}
And as you would expect:
> clang++ --version
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.2
Thread model: posix
> clang++ -std=c++11 test.cc
> ./a.out
test1 string conversion operator called
test2 string conversion constructor called
However, when changing t2's construction to initialization syntax:
test1 t1;
test2 t2 = t1;
return 0;
Clang outputs the following:
test.cc:23:15: error: no viable conversion from 'test1' to 'test2'
test2 t2 = t1;
^ ~~
test.cc:13:11: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'test1' to 'const test2 &' for 1st argument
class test2 {
^
test.cc:13:11: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'test1' to 'test2 &&' for 1st argument
class test2 {
^
test.cc:16:9: note: candidate constructor not viable: no known conversion from 'test1' to 'string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') for 1st argument
test2(string s) {
^
test.cc:8:9: note: candidate function
operator string() {
^
1 error generated.
I don't know if initialization is supposed to be able to perform an implicit conversion like this, but the error message seems very very wrong. no known conversion from 'test1' to 'string', yet it even shows candidate function operator string() {
What gives? And what does the C++ standard say about implicit conversions in initialization constructors? I assume that this should be counted as two implicit conversions, and thus not allowed, but the compiler output doesn't suggest that at all.
回答1:
First off, it's wrong to call test2::test2(string)
an "explicit conversion constructor". It'll be used in implicit conversions (mark it explicit
if you don't want that).
Anyway, clang's error message is spot on and it almost perfectly explains what's going on.
This:
test2 t2(t1);
is called direct initialization. All constructors for test2
are candidates and additionaly, compiler can run an implicit conversions sequence to match the arguments. It finds test1::operator string
and test2::test(string)
and all is well.
This:
test2 t2 = t1;
is called copy initialization. The expression on the right of =
needs to be converted to test2
and then either a copy- or move-constructor will be called to construct the object (in theory at least, it can later be elided as an optimization, but it must be accessible nonetheless).
来源:https://stackoverflow.com/questions/20008689/why-is-a-conversion-operator-not-called-when-using-initialization-syntax-and-wh