Why does explicit copy constructor cause error here? [duplicate] - c++

This question already has answers here:
Explicit copy constructor
(3 answers)
Why adding `explicit` to a defaulted copy constructor prevents returning an object? [duplicate]
(1 answer)
How come I can't use explicit constructor for constructing a return type
(3 answers)
Closed last month.
I thought that when you do:
Foo f1;
Foo f2 = f1;
The line Foo f2 = f1; calls the copy constructor of Foo and that it was equivalent to:
Foo f1;
Foo f2{f1};
However this seems not to be the case:
class Foo
{public:
Foo() {}
explicit Foo(const Foo& other) {}
};
int main()
{
Foo f1;
//Foo f2 = f1; // DOESN'T WORK IF COPY CONSTRUCTOR MADE EXPLICIT
Foo f2{ f1 }; // THIS WORKS WITH EXPLICIT
}
Why is this if there's no conversion? 'f1' is a Foo object, there shouldn't be a conversion. Why does it fail? Also in the following:
Foo funcReturningFoo()
{
Foo f;
return f; /* NO SUITABLE COPY CONSTRUCTOR IF MADE EXPLICIT */
}

Related

Why does the compiler throw an error saying overloaded constructor is ambiguous? [duplicate]

This question already has answers here:
Ambiguous constructor call
(3 answers)
Closed 2 years ago.
The Example class is shown below:
class Example
{
public:
Example(): x_(0) {} // problematic constructor
Example(int x = 1): x_(x){} // not problematic constructor
int getX() { return x_; }
private:
int x_;
};
Testing out Example in main:
int main()
{
// problem with this constructor
Example example1;
auto x1 = example1.getX();
// no problem with this constructor
Example example2(500);
auto x2 = example2.getX();
}
Issue Solved:
Eliminate constructor ambiguity by removing the default parameter values in the 2nd constructor. The constructors would look as follows:
Example(): x_(0) {}
Example(int x): x_(x){}
This would not violate the rules of cpp constructor overloading that lead to ambiguity.
Default value for argument makes call to default constructor ambiguous. Which function this would call, the first constructor, or the second one?
Example example1 = Example(); // equivalent of Example example1;
Only solution is not to form such declarations. Constructor with all arguments defaulted is equal to constructor with no arguments.
class Example
{
public:
Example(int x = 0): x_(x){} // same as default constructor
int getX() { return x_; }
private:
int x_;
};

what's the difference between the two copy constructor invocation in C++?

Look at the following codes:
class Foo
{
public:
Foo(){}
explicit Foo(const Foo &){}
};
int main()
{
Foo foo1;
Foo foo2(foo1);
Foo foo3 = foo1; //can not compile
return 0;
}
Why Foo foo3 = foo1; can not compile, and what's the difference between the two copy constructor invocation?
ps: My compiler tools is GCC4.8.2
Foo foo2(foo1); is direct initialization. Foo foo3 = foo1; is copy initialization. The difference between them is
Copy-initialization is less permissive than direct-initialization: explicit constructors are not converting constructors and are not considered for copy-initialization.
The copy constructor of Foo is declared as explicit, which is not considered in copy initialization.

What is the difference between the two initialization: Foo f(); Foo f = Foo()

class Foo
{
public:
Foo(){}
private:
Foo(const Foo &);
};
Foo f();
Foo f1 = Foo();
I find that when I declare Foo(const Foo &) to private, Foo f1 = Foo(); does not compile。 so I think Foo f1 = Foo(); just invoke copy constructor ,but when I change my code to:
class Foo
{
public:
Foo(){}
Foo(const Foo &){std::cout<<"Foo(const Foo &)";}
};
Foo f();
Foo f1 = Foo();
It doesn't print anything。So What is the difference between the two initialization: Foo f(); Foo f = Foo() ?
Due to copy elision the copy-constructor doesn't have to be called. The copy-constructor must still exist as a public member though.
And Foo f(); declares a function named f, taking no arguments and returning a Foo object by value.
To answer the actual question, formally, the code
Foo f1 = Foo();
uses the default constructor to create a temporary object of type Foo and uses the copy constructor to construct f1 as a copy of that temporary object, then it destroys the temporary object.
Foo f;
uses the default constructor to create f.
That little dance with the copy constructor isn't as inefficient as it sounds. Back in the olden days, as long as the copy constructor was accessible, the compiler was allowed to skip the temporary, and directly initialize f1. This is referred to as "copy elision". The resulting code is the same as Foo f1;. However, if Foo did not have a copy constructor, or the constructor was not accessible at the point of the initialization (for example, the copy constructor is private and the initialization is not done inside a member function), then the code was not valid.
Then copy elision became mandatory: the compiler is no longer just allowed to skip the temporary; it's required to.
And now, apparently, it's no longer even required that the copy constructor exist and be accessible; the compiler is required to transform the first form into the second, so the two are identical.

My constructor specifies at least one value for construction, and yet it can be default constructed

Take the following class:
class Foo{
public:
Foo(std::string bar_, int baz_ = 7)
:bar(bar_)
,baz(baz_)
{}
private:
std::string bar;
int baz;
};
Since Foo(std::string bar_, int baz_ = 7); is my only constructor, the compiler shouldn't implement a default constructor for me right? I would think that the only two ways I could construct this class are:
Foo foo("foo");
//or
Foo foo("foo",0);
//plus copy constructor and overloaded assignment operator.
Yet, why is this possible?
int main(){
Foo foo();
}
I don't understand how I can default construct a class when the only public constructor requires a value for its first parameter. Making the default constructor private or trying to C++11 delete it, makes no difference. How is this happening?
http://ideone.com/CL7IZo
Because Foo foo(); is a forward declaration of a function which returns a Foo and takes no arguments. Use Foo foo; instead and you will get your error.

class Bar { operator Foo(); }

What does this style of operator overloading mean?
class Foo {
Foo(int a) { ... }
};
class Bar {
operator Foo() { return Foo(25); }
};
That is user-defined conversion function which converts an instance of Bar into Foo implicitly.
Bar bar;
Foo foo = bar; // bar implicitly converts into Foo.
It is as if you've written this:
Foo foo = Foo(25);
If you've such a conversion function, then you can call this:
void f(Foo foo); //a function which accepts Foo
f(bar); // bar implicitly converts into Foo.
So such implicit conversion may not be desirable sometime, as it might cause problem, producing unintended result. To avoid that, you can make the conversion function explicit as (in C++11 only):
//valid in C++11 only
class Bar {
explicit operator Foo() { return Foo(25); }
};
Now both of these would give error:
Foo foo = bar; //error
f(bar); //error
However, the following is allowed:
Foo foo = static_cast<Foo>(bar); //Ok
f(static_cast<Foo>(bar)); //Ok
It's an overload of the cast operator. Best documentation I could find was MSDN
Basically, if you have a Bar you can cast it to a Foo which is constructed with a specific value:
Bar b;
Foo f = b;