Reputation: 803
How to initialize function parameters or function return values when the type has no copy constructor and only explicit constructors? For example:
struct A { };
struct B {
B(const B&) = delete;
explicit B(const A&) {}
};
void foo(B) {}
B bar() {
A a;
return ...; // how to return a?
}
int main() {
A a;
foo( ... ); // how to pass a?
}
return a
/ foo(a)
does not work because constructor B(const A&)
is explicit. return B(a)
/ foo(B(a))
does not work because copy constructor is deleted.
My intention is to know the language rules. To me it looks like a flaw in the language that, considering the presented type B, I can initialize locals, statics and class members but apparently neither function parameters nor function return values.
Upvotes: 0
Views: 95
Reputation: 2250
I think your issue is a misconception:
You do not initialize function parameters or return values with the constructor.
Instead you hand in parameters to a function, handing in means copying them.
Depending on the function signature either the variable itself is copied (void foo(B b)
) or the reference/pointer to it is copied.
In the first case you need a copy constuctor for your type, while you do not need one for references/pointers.
The same is true for returning values (!) from a function. You also need a copy constructor there. But you deleted the copy constructor, thus the compile errors.
With C++11 move semantics were added as an optimisation opportunity. When a move constructor is available r-values will be moved in/out of functions automatically instead of copied. Returning a local variable will also move it out instead of copying.
Since you declared a copy consturctor (no matter if as deleted/default) no move related functions will be created by the compiler. And thus also the automatic moving fails.
Upvotes: 0
Reputation: 141638
B(const B&) = delete;
, without an explicit definition of move-constructor, means the object cannot be copied or moved.
This means that you cannot pass by value, either as a parameter or as a return.
The explicit constructor is a red herring.
If you don't want to change B
to enable copying or moving, then you will have to pass by reference.
Upvotes: 1
Reputation: 69912
answers in annotated code below:
struct A { };
struct B {
B(const B&) = delete;
B(B&&) = default; // how to return B - pt 1 : move constructor
explicit B(const A&) {}
};
void foo(B) {}
B bar() {
A a;
return B(a); // how to return B - pt 2 : explcitly convert it
}
int main() {
A a;
foo(B(a)); // how to pass a - explicit conversion
}
Upvotes: 0