G B
G B

Reputation: 3024

Assign to object being created in c++

I'm writing some functions to operate on vector data.

I defined the objects non-copyable (private copy constructor and assignment operator).

Then I defined the templated operator =

template <typename G>
inline const TMatrix &operator=(const G &gen) {
    ir_mat::Copy<G, Dimension>::start(m_data, gen);
    return *this;
}

and some extra operators, like '+', '*', as described in this article.

Now I can assign the result of an expression to an object:

Vector3f v1, v2, v3;
v1 = v2 + v3;

Why can't I declare a variable and assign it in a single statement?

Vector3f v1, v2;
Vector3f v3 = v1 + v2;

Is it because this assignment tries to create a temporary object before instantiating the variable, and then copy it into the new object? Can I use my operator '=' also for instantiating new objects, without temporary storage? Do I have to define a special constructor for that?

Update

I also defined a templated copy constructor (in its simplest form, probably):

template <typename G>
TMatrix(const G &data) {
    operator=(data);
}

Now I can also instantiate v3 as:

Vector3f v3(v1 + v2);

But still no luck with the other assignment:

Vector3f v3 = v1 + v2;

Upvotes: 1

Views: 129

Answers (2)

Omnifarious
Omnifarious

Reputation: 56068

This initialization:

 Vector v3(v1 + v2);

will call your nice templated constructor.

This initialization:

 Vector v3 = v1 + v2;

ends up getting translated to this:

 Vector v3(Vector(v1 + v2));

Essentially the compiler tries to use the copy constructor and in so doing attempts to figure out how to convert the initializer to the appropriate type.

Choosing to create a type that's assignable to from random types, but can't be copy assigned or copy constructed is a very weird choice. I see that my assumption that you're doing it to avoid temporaries is correct. Except you're not doing that because temporaries are expensive exactly, but because you want to be building up an expression that will be evaluated later. Presumably because you want to vectorize complex expression evaluation.

Yes, you won't be able to use the assignment form of initialization then for that. At least, I can't think of a way to make it work.

My suggestion would be to somehow transform Vector into being just a handle for the expression you're building. That handle could be a handle to a real vector that's an input. Or it could be the handle to a VectorExpression that's the result of operating on vectors.

If you don't want shared ownership of the objects you have handles to, you still won't be able to implement copy assignment or copy construction. But in C++11 you could still implement move construction and move assignment of the handle.

Upvotes: 3

Joseph Mansfield
Joseph Mansfield

Reputation: 110698

Initialising an object of class type with the = initialisation syntax does not use operator=, it uses the copy constructor. That is, Vector3f v3 = v1 + v2; is just the same as Vector3f v3(v1 + v2);. If your copy constructor is not accessible, you will not be able to do this.

operator= is only ever called on an object that has already been constructed (as with v1 = v2 + v3), and in the form T& operator=(const T&) is known as copy assignment.

Upvotes: 3

Related Questions