zzzhhh
zzzhhh

Reputation: 53

Why is implicit conversion not allowed in the copy form of initialization when I do not specify explicit?

In C++, I know we cannot use an explicit constructor with the copy form of initialization (with an =) when implicit conversion happens. In other words, we can use the copy form of initialization if explicit is not specified when implicit conversion happens.

So, in the following code snippet:

#include <string>

class A {
public:
    A(const std::string& s = std::string()) :
        ps(new std::string(s)) { }

    A(const A& p) :
        ps(new std::string(*p.ps)), i(p.i) { }
    A& operator=(const A&);
    ~A() { delete ps; }
private:
    std::string* ps;
    int i;
};

A& A::operator=(const A& rhs) {
    auto newp = new std::string(*rhs.ps); 
    delete ps; 
    ps = newp; 
    i = rhs.i;
    return *this; 
}

int main() {
    A v = "abc";
}

My expectation is that "abc" can be implicitly converted to const std::string and thus the first constructor A(const std::string& s) will be called. Since I did not specify explicit for this constructor, I don't see anything that prevents this. But I get an error saying:

cannot convert from 'const char [4]' to 'A'

In the book "C++ Primer", I read "explicit Constructors Can Be Used Only for Direct Initialization" in section 7.5.4 "Implicit Class-Type Conversions". I think my understanding is that such an implicit conversion in the copy initialization form is not allowed only when the constructor is explicit.

But, I did not specify that, and there is only one conversion involved. So, I think A v = "abc"; should have worked. I don't understand why it can't.

=================================================== To the people who closed my question: I am not asking "How many implicit conversions" are allowed. I clearly know that no more than one implicit conversion are allowed. The crux of my question is what is considered an implicit conversion. For example, why does the compiler not call the string Ctor to construct the variable when we already have a string from one implicit conversion? Why does the compiler make a further implicit conversion to call the copy Ctor? What change we can make to the code snippet to make these rules more clear by, say, adding explicit to one or two Ctors? Please don't hasten to close a question when you have not grasped the main idea and subtlety of the question. This is only harmful to this website.

If the people who closed my question is not convinced. NathanOliver thinks the copy form of initialization (with an =) must use copy Ctor. JaMiT soon comes up with an experiment: A v = std::string{"abc"};. It works, but it does not use copy Ctor even though it uses the copy form of initialization (with an =). Actually it uses the first string Ctor. Why?

Now we may add explicit to the first string Ctor, and an error occurs. The "C++ Primer" text says "One context in which implicit conversions happen is when we use the copy form of initialization (with an =) (§ 3.2.1, p. 84). We cannot use an explicit constructor with this form of initialization;" From this sentence, the error is because we use = AND there is implicit conversions. But there is no implicit conversion in this experiment. So why the error?

Now you may argue that this is because "we must use direct initialization" as the text claims. But if we change the definition of variable v to A v = A(std::string("abc")); there will be no error. This is the copy form of initialization (with an =), and the string Ctor is still explicit. How to explain?

So, my question can be digged deeper than the so-called duplicated question. It is brusque to close my question and we consequently lost the chance to learn more from my question.

============================================================

Although I appreciate the comments, they are incorrect. The error in my original question has nothing to do with more than one implicit conversion or must call copy Ctor for the copy form of initialization (with an =). The reason is missing suffix of s that is needed to convert string literal to std::string. If writing A v = "abc"s; (together with using namespace std::string_literals;), the literal is converted to std::string and the string Ctor is called to construct v. If the question was not closed, maybe someone could point out this issue, but look at what some powerful politicians of SO have done. Now the question can really be closed.

Upvotes: 1

Views: 47

Answers (0)

Related Questions