Parallel assignment in C++ - c++

Is there any way of doing parallel assignment in C++? Currently, the below compiles (with warnings)
#include <iostream>
int main() {
int a = 4;
int b = 5;
a, b = b, a;
std::cout << "a: " << a << endl
<< "b: " << b << endl;
return 0;
}
and prints:
a: 4
b: 5
What I'd like it to print ... if it weren't obvious, is:
a: 5
b: 4
As in, say, ruby, or python.

That's not possible. Your code example
a, b = b, a;
is interpreted in the following way:
a, (b = b), a
It does nothing. The comma operator makes it return the value of a (the right most operand). Because assignment binds tighter, b = b is in parens.
The proper way doing this is just
std::swap(a, b);
Boost includes a tuple class with which you can do
tie(a, b) = make_tuple(b, a);
It internally creates a tuple of references to a and b, and then assigned to them a tuple of b and a.

Parallel assignment is not supported in C++. Languages that support this usually treat a,b,c as a list on either side of the assignment operator, this isn't the way the comma operator works in C++. In C++, a, b evaluates a and then b, so a, b = b, a is the same as a; b = b; a;.

Or Perl. But no, it's not possible (as far as I'm aware), you need to use a temporary variable, as in:
int a = 4;
int b = 5;
{
int tmp = a;
a = b;
b = tmp;
}
FYI, internally those languages (or Perl atleast) create a temporary list { a, b }, then assign the list to the two variables. In other words, this is atleast as performant, if only a little more messy.

This question is very old – I just stumbled into it today...
...and wondered why nobody gave this answer before...
I think, it's possible to do it in C++11 similar like Python does it (under the hood):
#include <iostream>
using namespace std;
int main()
{
int a = 4, b = 5;
cout << "Before assignment: a: " << a << ", b: " << b << endl;
pair<int&, int&> ba(b, a);
ba = make_pair(a, b); // <===: (b, a) = (a, b)
cout << "After assignment : a: " << a << ", b: " << b << endl;
return 0;
}
I tried this out on ideone.com. The output was:
Before assignment: a: 4, b: 5
After assignment : a: 5, b: 4
If I remember right (I'm not a Python expert), in Python, a, b denotes a pair. (Python Doc.: 5.3. Tuples and Sequences)
Such pair can be done in C++ 11 easily e.g. with std::pair. In this case, I made a pair of references and assigned the pair of values. It works as the make_pair() loads both variables before the right pair (of values) is assigned to the left pair of references.
Scrolling again, I realize that this answer is close to the boost based solution of Johannes answer.
May be, the reason is that it didn't work in C++03. I tried in coliru.stacked-crooked.com: With -std=c++03 it yields terrible to read compiler errors – changing to -std=c++11 and it compiles and executes fine as described above.
Disclaimer
I just cannot imagine what this solution is good for nor what practical worth it may have. This is not what I tried to do. As many other answers states "It does not work." IMHO it does (spelling it right according to the C++ language)...

Or Lua...
There are tricks with C/C++, like using xor or operations, but with risk of overflow and such. Just do it the painful way, with three assignments. Not a big deal.

There is no such function in the Standard Library. You could write a set of template functions :
template <typename T1> void ParAssign(T1& Lhs_1, T1 const& Rhs1);
template <typename T1, typename T2> void ParAssign(T1& Lhs1, T2& Lhs2, T1 const& Rhs1, T2 const& Rhs2);
// etc.
ParAssign(a,b,
b,a);
That's non-trivial if there is aliasing, as in your swap example.

Related

Making a list of generators (vector of lambdas) leads to very strange behavior with capture-by-reference

The following code is fairly similar to my actual application. Basically, I am trying to create a vector of functions so that I can generate a very large output in segments. I don't fully understand how the capture by reference [&] is working / should be working, and it's leading to some weird behavior.
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
template <typename T>
T add(const T& a, const T& b) {
return a + b;
}
template <typename T>
T add(const T& a, const T& b, T x) {
return (add<T>(a,b)*x);
}
int main() {
std::cout << "Hello World!\n";
vector<function<long ()>> funks;
for (long i = 1; i < 12; ++i) {
//auto funky = std::bind(add<int>, i, i*i);
std::cout << "PROOF: " << add(i, i*i, 2L) << std::endl;
function<long ()> funky = [&]() -> long {
long V = i;
return add(V, V*V, 2L);
};
funks.push_back(funky);
}
for (auto&& x : funks) {
std::cout << x() << " ";
}
}
The output of running each x in funks is: [312, 312, 312 ... 312] corresponding to i = 13
However, I don't understand why this is the case, as I reinitialize V for each lambda, and the output should be [4, 12, 24, 40, ... 264]
It works when I change the capture clause to [=], but in my actual application the inputs will be quite large so I'd prefer to copy as few times as possible.
EDIT: I should clarify exactly what I'm looking for. I'd like to make a vector of N functions, [f_0, f_1, ... f_N], such that when calling f_i(), it calls F(V_i) for some large (known) function F and large V_i.
The reason I want to capture by reference is that I don't want to copy the V_i even once, but the result of my implementation is that every f_i() ends up calling F(V_N)
You are auto-capturing i by reference in your loop, but it's only a binding. The value is not actually used until after the loop, when calling the lambda. At that point, each call takes the captured "reference to i" (which is actually undefined behavior, given that i is no longer in scope), dereferences it and stores the value in V. You know the rest.
What is strange is that you are insisting on using references to integer values. It's likely the compiler is doing its best to inline these and just use plain copies, but you should consider that when you have a reference, you can often expect additional instructions to be generated to dereference that to a value. For primitive types, just copy.
Oh, and definitely capture i by value!!! As a matter of style, I prefer to be explicit about my captures:
function<long ()> funky = [i]() -> long {
long V = i;
return add(V, V*V, 2L);
};

Is there a nice way to assign std::minmax(a, b) to std::tie(a, b)?

std::tie(a, b) = std::minmax(a, b);
I think this is intuitive code. Clean and understandable. Too bad it doesn't work as intended, as std::minmax templates for const&. If therefore the values are swapped inside the std::pair<const&, const&> than one assignement will overwrite the other value:
auto[a, b] = std::make_pair(7, 5);
std::tie(a, b) = std::minmax(a, b);
std::cout << "a: " << a << ", b: " << b << '\n';
a: 5, b: 5
The expected output here is a: 5, b: 7.
I think this is important as implementing transform functions to apply a function onto some ranges requires such statements for intuitive lambdas. For example:
std::vector<int> v{ 0, 1, 0, 2, 0 };
std::vector<int> u{ 1, 0, 1, 0, 1 };
perform(v.begin(), v.end(), u.begin(), [](auto& a, auto& b){
std::tie(a, b) = std::minmax(a, b);
});
//v would be == {0, 0, 0, 0, 0}
//u would be == {1, 1, 1, 2, 1}
One solution I found was constructing an std::tuple explicitly without any reference qualifiers over the std::pair<const&, const&> to enforce a copy:
std::tie(a, b) = std::tuple<int, int>(std::minmax(a, b));
But this <int, int> redundancy seems rather awful, especially when having saidauto& a, auto& b before.
Is there a nice, short way to perform this assignement? Could it be that this is the wrong direction and just saying if (a >= b) { std::swap(a, b); } would be the best approach here?
You can use an initializer list for minmax:
std::tie(a, b) = std::minmax({a, b});
This causes temporary objects to be created, just like when using unary plus, but has the benefit that it works with types lacking the unary plus operator too.
using namespace std::string_view_literals;
auto [a, b] = std::make_pair("foo"sv, "bar"sv);
std::tie(a, b) = std::minmax({a, b});
std::cout << "a: " << a << ", b: " << b << '\n';
Output:
a: bar, b: foo
Could it be that this is the wrong direction and just saying if (a >= b) { std::swap(a, b); } would be the best approach here?
I'd make it if(b < a) std::swap(a, b); because of the Compare1 requirement, but yes, I suspect that'll be faster and it's still very clear what you want to accomplish.
[1]
Compare [...] The return value of the function call operation applied to an object
of a type satisfying Compare, when contextually converted to bool,
yields true if the first argument of the call appears before the
second in the strict weak ordering relation induced by this type, and
false otherwise.
You can enforce this with a certain level of brevity as follows.
std::tie(a, b) = std::minmax(+a, +b);
std::cout << "a: " << a << ", b: " << b << '\n';
Explanation: the builtin unary plus operator, for the sake of symmetry with its unary minus sibling, returns its operand by value (it also performs the usual arithmetic conversions, but that doesn't apply to ints). This means it has to create a temporary, even though this temporary is nothing but a copy of the operand. But for the usage of minmax in this example, it's sufficient: swapping references here doesn't assign through anymore, because the references on the right hand side (the const int& arguments passed to minmax) don't refer to the same objects as those on the left hand side (inside the tuple of references created by std::tie).
The output is as desired:
a: 5, b: 7
Sometimes, taking a step back and finding a different way pays off:
if (b < a)
std::iter_swap(&a, &b);
That's concise and generally more efficient, certainly at least on par. Maybe pack it into its own function:
template <class T>
void reorder(T& a, T& b)
noexcept(noexcept(b < a, void(), std::iter_swap(&a, &b))) {
if (b < a)
std::iter_swap(&a, &b);
}
I'm using std::iter_swap() so I don't have to use the using std::swap; swap(a, b) two-step for generality in pre-C++2a, which introduces customization point objects making that obsolete.

What does `std::swap` do when applied to these objects?

The code
using namespace std;
class A
{
private:
vector<int> a;
public:
A(vector<int> x):a(x){}
string toString()
{
string s;
for (auto& element : a)
{
s += to_string(element) + " ";
}
return s;
}
};
int main()
{
A a1({1,2,3});
A a2({11,12,13});
cout << "a1 = " << a1.toString() << "\n";
cout << "a2 = " << a2.toString() << "\n";
swap(a1,a2);
cout << "a1 = " << a1.toString() << "\n";
cout << "a2 = " << a2.toString() << "\n";
return 0;
}
outputs as expected
a1 = 1 2 3
a2 = 11 12 13
a1 = 11 12 13
a2 = 1 2 3
From cplusplus.com > std::swap under complexity
Non-array: Constant: Performs exactly one construction and two assignments (although notice that each of these operations works on its own complexity).
Array: Linear in N: performs a swap operation per element.
Does it mean that std::swap when applied to a1 and a2 only swaps the pointers to the arrays [1,2,3] and [11,12,13] but does not copy any int or anything else?
What exactly does std::swap does when applied to two objects of the class A?
Assuming the std::swap copies all elements of the array, should I write a static A::swap function, using vector::swap whose time complexity is constant (from cplusplus.com > vector::swap) meaning that it only swaps the pointers?
[..] want to add a note that the semantics of std::swap is changed in C++17. So it might be a good idea to mention compiler, version of it and what standard you target.
I was hoping that a simple looking question would not have brought about complexities about C++ standards and compiler versions. I typically compile my code in C++11. For the sake of completeness here is the gcc version on my laptop.
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.3.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
There is a requirement that the type parameter to the std::swap template
is MoveConstructible and MoveAssignable. This suggests that the swap can be written roughly as (a few bits omitted)
void swap(T &a, T &b) {
T tmp{std::move(a)};
a = std::move(b);
b = std::move(tmp);
}
For your example class, it'll invoke the default move ctor/move assignment operators (edit: of A) a few times and they in turn will invoke those of std::vector.
IOW, you can expect your program to be reasonably efficient as is.
Alternatively, you can define a non-member swap function in the same namespace as A and call explicitly std::swap with vector parameters. Or call directly std::vector::swap.
Depending on your compiler and the classes/types you are using the swap function will either copy one of the classes, or use the move constructor/assignment (C++11 and upwards) (http://en.cppreference.com/w/cpp/utility/move).
Your class only consists of a vector and for vector classes this move constructor does what you refer to as simply "swapping pointers", so it will be very quick. Just be aware that implementing e.g. a copy constructor will delete the implicitly-declared move constructor which makes this 'magic' happen!! (http://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor)
While looking at the swap function independently, I'm giving you an avalanche of followup-insights:
One of the most famous uses of the swap-function happens in the copy-and-swap idiom (https://progdoo.wordpress.com/2012/06/03/c11-copy-and-swap-idiom/). This works most efficiently with implemented move-constructors/assignments.

The rationale of C++ disallowing array of functions?

What is the underlying rationale (technical or conceptual) that C++ does not allow defining array of function type? E.g.
using fn_t = int(int);
fn_t ary[2]; // ERROR (ref: ISO/IEC-14882 [dcl.array])
Given two random functions I just made up:
int a( int x, int y )
{
return x * y;
}
int b( int x, int y )
{
int result = 0;
for (int xi = 1; xi <= x; xi++)
for (int yi = y; yi > 0; yi--)
result += xi * xi;
return result;
}
How do you suggest I put them in an array?
I could compile them, I suppose, then just have an array of max( sizeof(a’s bytecode), sizeof(b’s bytecode) ). But now I have some additional considerations:
Where does this array go?
Some processors can run code from anywhere in memory. Some cannot.
What about security attributes for the code?
What about relocation considerations?
How do I call this function?
Can I use the processor’s usual calling conventions?
Or will this require extra behind-the-scenes magic?
What happens when I want a pointer to the array?
What happens if I move the array and then call the pointer?
What about exceptions and other abnormal signal considerations?
This is just the tip of the iceberg. There are a lot of technical considerations to doing this kind of thing.
Which leads to the main consideration:
What advantage would this give over pointers to functions?
With a pointer to a function, I can do everything I otherwise wanted to do:
int (*fs)(int,int)[] = { a, b };
int x = fs[0]( 10, 10 );
int y = fs[1]( 10, 10 );
The language is designed with several goals — two of the most important being simplicity and flexibility.
Doing what you would reduces both simplicity and flexibility for everyone: compiler writers, compilers themselves, runtime management, speed, safety, etc.
EDIT:
tl;dr Because it offers no advantage over pointers or references to functions, but plenty of drawbacks.
What is the underlying rationale (technical or conceptual) that C++ does not allow defining array of function type?
What is a function? It's just some code at an address. Conceptually it's a singleton, since there is no reasonable way to copy one or allocate one on the heap. Why would you? It already exists. It has a name, and that name yields a function pointer - the address of the code.
There is a concept of a 'function object', which is more equivalent to the 'first class function' of high level languages like python or javascript.
But under the hood it's modelled as a structure containing the address of code (a function pointer) and some state.
There are a few ways to create an array of functions: (this code is c++14)
#include <functional>
#include <iostream>
int a(int i) {
std::cout << "called a with " << i << std::endl;
return i;
}
int b(int i) {
std::cout << "called b with " << i << std::endl;
return i + 1;
}
int c(int i) {
std::cout << "called c with " << i << std::endl;
return i + 2;
}
int main()
{
// make life easier by creating a typedef
using raw_fptr = int (*)(int);
// an array of function pointers
raw_fptr raw_ptrs[] =
{
a, b, c
};
// a typedef of a std::function object
using fobject = std::function<int(int)>;
// an array of function objects
fobject fobjects [] = {
&a, // can capture a function pointer
[](int i) -> int { // or a lambda
return b(i);
},
std::bind(&c, std::placeholders::_1) // or a binder
};
for (auto&& f : raw_ptrs)
f(0);
for (auto&& f : fobjects)
f(1);
}

Order of elements in set of pointers

Why does the following code get compiled even though I have commented the A::operator<. I wonder how the output of the following code is printed in ascending order without the < operator. How can I change the order to descending? (note: this code does not get compiled if I use A instead of A* unless I provide a definition for A::operator<)
#include <iostream>
#include <set>
using namespace std;
class A
{
public:
A(int v):x(v){}
virtual ~A(){}
int x;
/*bool operator<(const A &a) const
{
return x > a.x;
}*/
};
int main()
{
set<A*> numbers;
A* a1 = new A(1);
A* a2 = new A(2);
A* a3 = new A(3);
numbers.insert(a2);
numbers.insert(a3);
numbers.insert(a1);
for(set<A*>::iterator itr = numbers.begin();itr!=numbers.end();itr++)
{
cout << (*itr)->x << endl;
}
// output: 1 2 3
return 0;
}
Your code gets compiled because you have a set of pointers. Since the set contains pointers, and your operator does not compare pointers, but rather, objects of type A, it is not needed for the set. There is an existing pointer less-than comparison operator, which is what gets used in your set.
You can change the ordering by providing your own comparator implementing strict weak ordering:
struct APtrComp
{
bool operator()(const A* lhs, const A* rhs) const { /* implement logic here */ }
};
And instantiate your set using it as second template parameter.
set<A*, APtrComp> numbers;
you have a set of pointers. usually pointers are allocated in increasing order. and pointers have a default < operator. so this is why it's compiling and working.
P.s. it will print you the value of A1 A2 A3 in this order no matter what's there values:
...
A* a1 = new A(9);
A* a2 = new A(5);
A* a3 = new A(1);
...
// output: 9 5 1
If you remember your pointer arithmetic, all points are given a set of operators to use in operations(which includes the operator<). Your set will use this default operator < .
From what I understand you want to know why the code compiles with A* even if you dont have the operator< and how to change the order from ascending to descending.
It compiles because it is using the operator< with the pointers address.
change cout << (*itr)->x << endl;
to cout << (*itr)->x << ' ' << *itr << endl; and you'll see it easily :)
It is normal that the code doesn't compile without the operator< if you're using the set<A>. It won't know what to compare in order to insert the members sorted. So you have to provide that operator!
If you want to keep using pointers, you can use the code provided by #juanchopanza.