Assignment of an operation without intermediate object - c++

Given a class like this:
class Vec{
int comp[2];
public:
void add(Vec& vec, Vec& vec2){
comp[0] = vec.comp[0] + vec2.comp[0];
comp[1] = vec.comp[1] + vec2.comp[1];
}
Vec operator+ (Vec& vec){
Vec res;
res.comp[0] = comp[0] + vec.comp[0];
res.comp[1] = comp[1] + vec.comp[1];
return res;
}
};
There are two member functions that essentially do the same thing, which is add two Vecs together. The difference, of course, is that there are no intermediate values involved in the add function, whereas operator+ declares a local object of Vec.
My question is, is there any way to define operator+ in combination with operator= to have the same semantics as add, having no intermediate values? The rationale is to decrease the amount of intermediate values involved, for efficiency, yet keep the elegance of the operator syntax.
The C++ interface for the GMP library apparently is able to do this: http://gmplib.org/manual/C_002b_002b-Interface-General.html#C_002b_002b-Interface-General
An important feature of the implementation is that an expression like a=b+c results in a single call to the corresponding mpz_add, without using a temporary for the b+c part.
I'm wondering if there is some possible way to do this, or would GMP have to use some sort of workaround for this?

This is a bad idea, because it violates the natural assumptions most people have about the behavior of operators.
Unfortunately it is also very important (especially for libraries like gmpxx, which want to offer natural code using operators, high performance, and have huge objects as arguments). How do they achieve this? By using expression templates they can optimize expression at compile time. The idea is that operators don't return values directly but concrete instances of expression classes which then can be manipulated with meta-programming.
Expression templates are an rather advanced topic and you should be relatively certain that it will give a significant benefit to your code. In your example the size of the vectors simply isn't relevant enough.
Wiki Expression Templates

I see no real advantage for this as your objects are very small. But for things like dynamically allocated large vectors this could be useful.
One way to implement it is to create a temporary noop class to hold the unevaluated expression. This class would be convertible to Vec so that it becomes transparent to the user. The point is that you can now create an specialized operator= for the add expression. Some code (fill the gaps):
struct VecAdd;
struct Vec
{
Vec& operator=(const VecAdd& vecadd) { /*...*/ }
};
struct VecAdd
{
const Vec& v1;
const Vec& v2;
operator Vec() { return Vec(/*...*/); } // for things like: f(v+u);
};
VecAdd operator+(const Vec& a, const Vec& b) { return VecAdd{a, b}; }
This is what GMP actually does. But with a lot of macros and templates to make the code less repetitive.

How about operator+= which you then would use as myVec += otherVec

Related

Design to avoid binding lvalue reference to temporary for data container and wrapper

I'm struggling with the design of a few (probably two) C++ classes that work together and implement sort of a data container (Vector) and a data wrapper (Integer) that wraps individual vector elements (or better to say the access to it).
The Vector simply holds a vector of int.
The Integer/wrapper provides access to an int (possibly without holding it).
Requirements:
Wrapper/Integer must be available as lvalue
The data container should hold the data as an vector of int (not as a vector of Integer)
The wrapper also holds some other data members (no reinterpreting cast int -> Integer possible)
I fail to design this (see below) without running into the problem where an lvalue reference cannot bind to a temporary. I understand that that's not possible and I understand that code is wrong (and why it's wrong). There's no need to explain that lvalue references can't bind to rvalues. I'm struggling to find a solution to above requirements without this problem.
How to design this in C++? (Can be any modern standard)
#include<vector>
class Integer
{
int& ref_t;
bool other_data_member;
public:
Integer(int& rhs): ref_t(rhs) {}
Integer& operator=( int i )
{
ref_t = i;
return *this;
}
};
class Vector
{
std::vector<int> data;
public:
Vector(): data(10) {}
Integer& operator[](int i)
{
return Integer( data[i] ); // caution: this doesn't work
}
};
void write_one( Integer& i )
{
i = 1;
}
int main()
{
Vector v;
write_one( v[5] );
}
Returning a “temporary” by value doesn’t make a copy or even a move (guaranteed as of C++17, though often implemented as a conforming optimization in prior versions). You have to do this, because your operator[] needs to form a new wrapper for whatever index. (The reinterpret_cast approach has undefined behavior regardless of other members of Integer.) Generic code can bind auto&& to your proxy object because of lifetime extension, and can assign to it, so often need not be aware of the proxy (as is desirable).
Separately, if you want to avoid copying arguments to functions like write_one that do know about the proxy type, you can accept const Integer&. To make that work, make your operator= const (which sounds weird until you remember that it’s not the Integer that’s being modified).

Emulate copy-assignment operator for lambdas in C++

This question has two parts
Firstly, can someone explain the rationale behind C++ disabling the copy-assignment operator for lambdas? If you're going to allow the copy constructor, why not the copy-assignment operator?
Secondly, how do you best overcome this limitation without forcing people to write C++03 style functors, or using std::function (the functions I'm dealing with are tiny, and I'd like the compiler to inline them wherever possible)?
Background:
I'm trying to implement a flat_map like operation in a stream processing library I'm writing, similar to flatMap in Scala or other functional languages. As a result, I need to create an iterator that iterates over a list of iterators. Each time the flat_map iterator is de-referenced a lambda associated with the inner iterator is executed. The outer iterator needs to switch the inner iterator each time the inner iterator reaches the end. Since the inner iterator contains a lambda, and therefore does not have a copy-assignment operator, it's not possible to switch it. Technically I could solve the problem using dynamic allocation, so that I always call the copy-constructor, but that doesn't seem like the right approach. Here is a snippet of code that might help highlight the problem:
template <typename Iter>
class flat_map_iterator {
public:
flat_map_iterator& operator++() {
++it_inner_;
if (it_inner_ == (*it_outer_).end()) {
++it_outer_;
// ERROR: cannot be assigned because its copy assignment operator is implicitly deleted
it_inner_ = (*it_outer_).begin();
}
return *this;
}
private:
Iter it_outer_;
typename Iter::value_type::iterator it_inner_;
};
Edit:
Thanks for the really quick responses. Here is a use case example:
int res = ftl::range(1, 4).map([](int a){
return ftl::range(a, 4).map([a](int b){
return std::make_tuple(a, b);
});
})
.flat_map([](std::tuple<int, int> x){ return std::get<0>(x) * std::get<1>(x); })
.sum();
assert(res, 25);
The ftl::range(begin, end) function returns a lazy iterator over the range [begin, end).
It's not that C++ disables the copy-assignment operator for lambda per-se, but that by default members in a lambda object are saved as const, and then the assignment operator can basically do nothing to assign to them, and so it is not generated. If you want lambdas to not hold members as const, you use the [...](...) mutable {...} syntax.
The other thing is that I'm not entirely sure what you get out of assigning lambdas. I mean, if you're going to re-use the lambda type (and functionality) and simply bind it to different variables, you're already working against the nice lambda capture syntax, and might as well have it be a normal function object. Assigning one type of lambda to another one is impossible. This means that you can not provide different lambda implementations when you hold the lambda itself by value.
If this is still what you're going for, I think dynamic allocation (e.g. using unique_ptr) is fair game.
And if you really want to avoid it, you could manually destruct and re-construct your lambda, as the following example illustrates:
#include <iostream>
template <class T>
struct LambdaContainer {
LambdaContainer(const T& lambda)
: lambda{lambda} {}
void resetLambda(const T& lambda) {
this->lambda.~T();
new (&this->lambda) T{lambda};
}
T lambda;
};
int main()
{
int i = 1;
auto l = [=]() {
std::cout << i;
};
using LT = decltype(l);
LambdaContainer<LT> lc{l};
lc.resetLambda(l);
}

Best Way to Return a Class in C++

I'm writing a C++ vector class for a project and I'm having a hard time making a decision about how best to write some of the methods. Before I start I will say that the class has a good copy constructor and assignment operator (this will be relevant in a sec). The class has a set of static methods that return vectors when I want to make sure that neither parameter is altered, they have signatures like:
Vector* Vector::subtract(const Vector* v, const Vector* u)
{
double outX = v->myX - u->myX;
double outY = v->myY - u->myY;
double outZ = v->myZ - u->myZ;
return new Vector(outX, outY, outZ);
}
The problem I am having is that I don't want to return pointers if I can help it. So instead I did some testing and realized that if I just say
return Vector(outX, outY, outZ)
and then assign the result like
Vector foo = Vector::subtract(bar, temp)
it will create a copy and work fine. Here's where my question lies: I just called the constructor twice (essentially) is there a way to get around that? Secondly, if I use this method as a argument to another method like
foo.multiply(&Vector::subtract(foo, bar), 5)
will it still create a copy or did I just pass the pointer that has gone out of scope in the Vector::subtract method?
More generally, what is the best (or at least is there a better) way to do this?
I just called the constructor twice (essentially) is there a way to
get around that?
Have you ever heard of Return Value Optimization? There is nothing you have to do. The compiler will most likely eliminate the copy for you. Now, if you use C++11 and the Vector class manages a resource, you could declare a move constructor also, so that the returned value is moved just in case the compiler decides it cannot perform RVO. However, it looks like the class only holds 3 values, if that is the case, copying is going to be as efficient as moving.
&Vector::subtract(foo, bar)
What is the & for? Was that a mistake? Also, the member function is not declared static so the syntax is wrong. Anyways, assuming subtract returns a copy, it will return a copy and pass that to the multiply function as an argument.
Also, on another note, Vector* Vector::subtract(const Vector* v, const Vector* u)
would be better as Vector* Vector::subtract(const Vector& v, const Vector& u), this makes the syntax cleaner when you pass arguments to subtract, etc.
So changing your code, it would look something like the following:
Vector Vector::subtract(const Vector& v, const Vector& u)
{
return Vector(v.myX - u.myX, v.myY - u.myY, v.myZ - u.myZ);
}
Returning pointers/references to dynamically allocated objects is never the way to go. And obvious example would be if your function is called recursively, who is responsible for de-allocating that memory?
I've read from a book (by Scott Meyers, it was Effective C++ Item #21) that the only safe way to do it was to return the object itself. What you could do is, IIRC, facilitate the compilers job at eliminating these objects that are essentially temporare (returned from one function to be fed to another without every being assigned to another) and one of those ways was to make it anonymous (aka as the Return Value Optimization, thanks to In silico for reminding me). Like so
return Vector(outX, outY, outZ);
as opposed to:
Vector v(outX, outY, outZ);
return v;
So my proposed signature for your subtract method comes down to:
Vector Vector::subtract(const Vector& v, const Vector& u)
You should avoid pointers as much as possible, not only in the return type but also in arguments to functions. Prefer references whenever possible, use pointers when you must.
If you change your functions to take the arguments by reference and return by value. Consider overloading operators when it makes sense in the domain (which I believe is the case here):
class Vector { ... };
Vector operator+( Vector const& lhs, Vector const& rhs ) {
return Vector( lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.y );
}
Vector operator*( Vector const& lhs, Vector const& rhs ) { ... }
Then you can chain operations at will:
Vector a(...), b(...);
Vector c = (a + b) * c;
Most compilers these days will implement what is called Return Value Optimization (RVO) to combat this problem. You're right that you shouldn't return pointers unless it's really necessary. That being said, you should probably be using references. All in all, if I was going to write this method, this is how I'd write it:
Vector Vector::subtract(const Vector& v, const Vector& u)
{
return Vector(v.myX - u.myX, v.myY - u.myY, v.myZ - u.myZ);
}

Using a class with const data members in a vector

Given a class like this:
class Foo
{
const int a;
};
Is it possible to put that class in a vector? When I try, my compiler tells me it can't use the default assignment operator. I try to write my own, but googling around tells me that it's impossible to write an assignment operator for a class with const data members. One post I found said that "if you made [the data member] const that means you don't want assignment to happen in the first place." This makes sense. I've written a class with const data members, and I never intended on using assignment on it, but apparently I need assignment to put it in a vector. Is there a way around this that still preserves const-correctness?
I've written a class with const data members, and I never intended on using assignment on it, but apparently I need assignment to put it in a vector. Is there a way around this that still preserves const-correctness?
You have to ask whether the following constraint still holds
a = b;
/* a is now equivalent to b */
If this constraint is not true for a and b being of type Foo (you have to define the semantics of what "equivalent" means!), then you just cannot put Foo into a Standard container. For example, auto_ptr cannot be put into Standard containers because it violates that requirement.
If you can say about your type that it satisfies this constraint (for example if the const member does not in any way participate to the value of your object, but then consider making it a static data member anyway), then you can write your own assignment operator
class Foo
{
const int a;
public:
Foo &operator=(Foo const& f) {
/* don't assign to "a" */
return *this;
}
};
But think twice!. To me, it looks like that your type does not satisfy the constraint!
Use a vector of pointers std::vector<Foo *>. If you want to avoid the hassle of cleaning up after yourself, use boost::ptr_vector.
Edit: My initial stab during my coffee break, static const int a; won't work for the use case the OP has in mind, which the initial comments confirm, so I'm rewriting and expanding my answer.
Most of the time, when I want to make an element of a class constant, it's a constant whose value is constant for all time and across all instances of the class. In that case, I use a static const variable:
class Foo
{
public:
static const int a;
};
Those don't need to be copied among instances, so if it applied, that would fix your assignment problem. Unfortunately, the OP has indicated that this won't work for the case the OP has in mind.
If you want to create a read-only value that clients can't modify, you can make it a private member variable and only expose it via a const getter method, as another post on this thread indicates:
class Foo
{
public:
int get_a() const { return a; }
private:
int a;
};
The difference between this and
class Foo
{
public:
const int a;
};
is:
The const int gives you assurance that not even the implementation of the class will be able to muck with the value of a during the lifetime of the object. This means that assignment rightfully won't work, since that would be trying to modify the value of a after the object's been created. (This is why, btw, writing a custom operator=() that skips the copy of a is probably a bad idea design-wise.)
The access is different – you have to go through a getter rather than accessing the member directly.
In practice, when choosing between the two, I use read-only members. Doing so probably means you'll be able to replace the value of an object with the value of another object without violating semantics at all. Let's see how it would work in your case.
Consider your Grid object, with a width and height. When you initially create the vector, and let's say you reserve some initial space using vector::reserve(), your vector will be populated with initial default-initialized (i.e. empty) Grids. When you go to assign to a particular position in the vector, or push a Grid onto the end of the vector, you replace the value of the object at that position with a Grid that has actual stuff. But you may be OK with this! If the reason you wanted width and height to be constant is really to ensure consistency between width and height and the rest of the contents of your Grid object, and you've verified that it doesn't matter whether width and height are replaced before or after other elements of Grid are replaced, then this assignment should be safe because by the end of the assignment, the entire contents of the instance will have been replaced and you'll be back in a consistent state. (If the lack of atomicity of the default assignment was a problem, you could probably get around this by implementing your own assignment operator which used a copy constructor and a swap() operation.)
In summary, what you gain by using read-only getters is the ability to use the objects in a vector or any container with value semantics. However, it then falls to you to ensure that none of Grid's internal operations (or the operations of friends of Grid) violate this consistency, because the compiler won't be locking down the width and height for you. This goes for default construction, copy construction, and assignment as well.
I'm considering making the data member non-const, but private and only accessible by a get function, like this:
class Foo
{
private:
int a;
public:
int getA() const {return a;}
};
Is this 'as good' as const? Does it have any disadvantages?
As of c++20, using const member variables are legal without restrictions that had made it virtually unusable in containers. You still have to define a copy assignment member function because it continues to be automatically deleted when a const object exists in the class. However, changes to "basic.life" now allow changing const sub-objects and c++ provides rather convenient functions for doing this. Here's a description of why the change was made:
The following code shows how to define a copy assignment member function which is useable in any class containing const member objects and uses the new functions std::destroy_at and std::construct_at to fulfil the requirement so the new "basic.life" rules. The code demonstrates assignment of vectors as well as sorting vectors with const elements.
Compiler explorer using MSVC, GCC, CLANG https://godbolt.org/z/McfcaMWqj
#include <memory>
#include <vector>
#include <iostream>
#include <algorithm>
class Foo
{
public:
const int a;
Foo& operator=(const Foo& arg) {
if (this != &arg)
{
std::destroy_at(this);
std::construct_at(this, arg);
}
return *this;
}
};
int main()
{
std::vector<Foo> v;
v.push_back({ 2 });
v.push_back({ 1 });
v.insert(v.begin() + 1, Foo{ 0 });
std::vector<Foo> v2;
v2 = v;
std::sort(v2.begin(), v2.end(), [](auto p1, auto p2) {return p1.a < p2.a; });
for (auto& x : v2)
std::cout << x.a << '\n';
}

Operator overloading for a class containing boost::numeric::ublas::matrix<double>

I have a class which contains a few boost::numeric::ublas::matrix's within it. I would like to overload the class's operators (+-*/=) so that I can act on the set of matrices with one statement.
However this seems to require temporary instances of my class to carry values around without modifying the original class. This makes sense to me, however, when I create a new instance within the function and return it I get:
warning: reference to local variable ‘temp’ returned
I'm pretty new to c++ and the examples of operator overloading seem to all return new temporary objects. I would also like to avoid the overhead in instantiating new matrix's, which leads me towards looping over all elements. How should I go about this? Performance is a concern.
If you're using boost already, I'd strongly suggest using boost::operators along with your example.
You'll get several benefits:
You'll only need to overload the +=/-=/= operators, and get the +/-/ operators for free.
You'll have a optimal implementation of the freely implemented operators.
You'll get rid of the problem you posted, because you'll be implementing the = versions, which require less design.
The conventional way of operator overloading is as follows. (I think)
Your in-place operators are defined as members, such as:
foo& operator+=(const foo& rhs);
foo& operator*=(const foo& rhs);
// etc.
Which simply do what they need on *this:
foo& operator+=(const foo& rhs)
{
// add elements together
return *this;
}
Then make free functions, and let the copying be done in the arguments:
const foo operator+(foo lhs, const foo& rhs)
{
return lhs += rhs;
}
The return value is const because it's strange to do:
foo a, b, c;
(a + b) = c;
In the same way it's strange to do:
int a, b, c;
(a + b) = c;
Though you'll get differing opinions on that. This is how you reuse your code, and have the copy done for you automatically. Very terse and readable.
Like Neil and I said above, though, if you're creating new data, at some point that data needs to have a new place to stay. Use mutating operators when you can to avoid this, but some things simply cannot be escaped.
It might not even be a problem. If it is, try to optimize the memory allocations you have; these are likely the slowest part. I'm not sure, but I think most boost classes let you specify an allocator. The boost memory pool library may be useful here.