Florian Kaufmann
Florian Kaufmann

Reputation: 803

How to initialize parameters / return values whose type has no copy constructor and only explicit constructors

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

Answers (3)

mfuchs
mfuchs

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

M.M
M.M

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

Richard Hodges
Richard Hodges

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

Related Questions