The std::minmax function introduced in C++11 is supposed to return a pair of respectively the lowest and the greatest of the given values.
In this example:
int a = 6, b = 5;
auto p = std::minmax(a, b);
std::cout << "p.first = " << p.first << std::endl;
std::cout << "p.second = " << p.second << std::endl;
This works as advertised and prints
p.first = 5
p.second = 6
Now I would like to effectively modify a and b to force b to be lower than a, as if running this code:
if (b > a)
std::swap(a, b);
So I have written this:
int a = 5, b = 6;
std::tie(b, a) = std::minmax(a, b);
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
However, this prints:
a = 5
b = 5
Using the initializer_list overload instead, like this:
std::tie(b, a) = std::minmax({a, b});
causes the expected result to be printed:
a = 6
b = 5
The compiler is GCC 4.7.1 (also tested with GCC 4.8.1 on Linux and Windows with Mingw-w64).
I have created an SSCCE at http://ideone.com/fA0qw5.
Why is the two-arguments overload not doing what it is supposed to do when using std::tie ?
The problem is that std::minmax returns references for the 2-argument version. That way, as soon as b in the std::tie(b, a) is assigned, the change is reflected in the b part of the returned std::pair, giving it the value of 5 - which in turn is assigned to the a in std::tie(b, a), yielding (5, 5) as the result.
Related
I have the following:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = std::bind(print_str, str);
f(); // correctly print: Hello
return 0;
}
I think the type of std::bind(print_str, str) is std::function<void(std::shared_ptr<std::string>)>, but the code above is correctly running. Is there any trick in std::bind?
env: centos, gcc82
What std::bind does is correct. It uses the value you provided (str) for the call to print_str. So you don't need to specify it anymore and will always be replaced by the bound value.
#include <iostream>
#include <functional>
int sum(int value1, int value2) {
return value1 + value2;
}
int main() {
std::function<int(int, int)> f1 = std::bind(sum, std::placeholders::_1, std::placeholders::_1);
std::function<int(int)> f2 = std::bind(sum, 10, std::placeholders::_1);
std::function<int()> f3 = std::bind(sum, 100, 200);
std::function<int(int)> f4 = std::bind(sum, std::placeholders::_1, 200);
int a = 1;
int b = 2;
std::cout << "the sum of " << a << " and " << b << " is: " << f1(a, b) << std::endl;
std::cout << "the sum of " << 10 << " and " << b << " is: " << f2(b) << std::endl;
std::cout << "the sum of " << 100 << " and " << 200 << " is: " << f3() << std::endl;
std::cout << "the sum of " << 200 << " and " << b << " is: " << f4(b) << std::endl;
return 0;
}
output:
the sum of 1 and 2 is: 2
the sum of 10 and 2 is: 12
the sum of 100 and 200 is: 300
the sum of 200 and 2 is: 202
f1 binds no values but placeholders and returns an int(int, int) like function
f2 binds one value and one placeholder and returns an int(int) like function
f3 binds two values and no placeholder and returns an int() like function
f4 is like f2 except that the place holder is now the first parameter instead of the second one.
Your code falls into the f3 case.
I think the type of std::bind(print_str, str) is std::function<void(std::shared_ptr<std::string>)>
No, the type of std::bind(print_str, str) is an unspecified functor type, something like
class binder
{
void(*f)(std::shared_ptr<std::string>);
std::shared_ptr<std::string> p;
public:
template<typename... Args>
void operator()(Args... ) { f(p); }
};
Note that this is callable with any arguments or none.
What you are experiencing here is correct and is precisely doing what std::bind was designed for.
Simply speaking:
It turns a function taking n parameters into a function taking m parameters (where n >= m).
In your particular case, you give it a function taking one parameter and get back a function taking zero parameters. This new function will internally call print_str and always pass str as argument.
Side note:
Since there are lambdas in C++11, std::bind is sort of redundant.
What you are doing is exactly equivalent to this:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = [=]() { print_str(str); };
f(); // correctly print: Hello
return 0;
}
This hopefully also helps understanding what std::bind does behind the scenes.
I thought that using structured bindings and auto& specifier I can obtain references to structure members and use them directly instead of going through the structure.
However, the following code works and the static asserts hold:
struct Test
{
int i;
char c;
double d;
};
Test test{ 0, 1, 2 };
auto& [i, c, d] = test;
i = 4;
c = 5;
d = 6;
// i, c, d are not references !
static_assert(!std::is_same_v<decltype(i), int&>);
static_assert(!std::is_same_v<decltype(c), char&>);
static_assert(!std::is_same_v<decltype(d), double&>);
cout << &i << " == " << &test.i << " (" << std::boolalpha << (&i == &test.i) << ")" << endl; // (true)
cout << test.i << ", " << (int)test.c << ", " << test.d << endl; // 4, 5, 6
But I thought C++ doesn't allow one variable to have more than one name except if one is the real variable and others are references but in this case the variable i is the same as test.i and neither of them is a reference.
In the array and type case, structured bindings aren't references - they're aliases to the corresponding members. The main reason for this is to support bitfields. You can't have a reference to a bitfield, but you can have an alias to one:
struct X {
uint8_t a : 2;
uint8_t b : 6;
};
void f(X& x) {
auto& [a, b] = x; // fine, a just means "x.a"
auto& a2 = x.a; // error
}
Separately from that, decltype() does something special on structured bindings - it will only ever give you a reference type if the member the binding refers to is a reference type, as in:
struct Y {
int& a;
int b;
};
void f(Y& y) {
auto& [a, b] = y;
// decltype(a) is int&, decltype(b) is int
}
I've come across this behavior of std::gcd that I found unexpected:
#include <iostream>
#include <numeric>
int main()
{
int a = -120;
unsigned b = 10;
//both a and b are representable in type C
using C = std::common_type<decltype(a), decltype(b)>::type;
C ca = std::abs(a);
C cb = b;
std::cout << a << ' ' << ca << '\n';
std::cout << b << ' ' << cb << '\n';
//first one should equal second one, but doesn't
std::cout << std::gcd(a, b) << std::endl;
std::cout << std::gcd(std::abs(a), b) << std::endl;
}
Run on compiler explorer
According to cppreference both calls to std::gcd should yield 10, as all preconditions are satisfied.
In particular, it is only required that the absolute values of both operands are representable in their common type:
If either |m| or |n| is not representable as a value of type std::common_type_t<M, N>, the behavior is undefined.
Yet the first call returns 2.
Am I missing something here?
Both gcc and clang behave this way.
Looks like a bug in libstc++. If you add -stdlib=libc++ to the CE command line, you'll get:
-120 120
10 10
10
10
This question already has answers here:
Swapping two variable value without using third variable
(31 answers)
Closed 6 years ago.
we usually use the
a=a+b;
b=a-b;
a=a-b;
logic to solve this code, however, if we work with int, then after say 30000 the code fails, if we take long, it fails after say 1000000 or so. My objective is, not to increase the length of the code yet, do the same operation. I have already tried using a BIT wise XOR,
a = a ^ b;
b = a ^ b;
a = a ^ b;
Still it didn't help, any ideas?
To swap a variable a and a variable b: std::swap(a, b);
Example:
int a = 10;
int b = 20;
std::cout << "Before swap\n";
std::cout << "Value of a: " << a << '\n';
std::cout << "Value of b: " << b << '\n';
std::swap(a, b);
std::cout << "After swap\n";
std::cout << "Value of a: " << a << '\n';
std::cout << "Value of b: " << b << '\n';
Output using GCC 4.9.2:
Before swap
Value of a: 10
Value of b: 20
After swap
Value of a: 20
Value of b: 10
This way of doing it uses rvalues internally, so it has next to zero overhead for other use cases and won't overflow for any primitive type ever
Can I confirm with stackoverflow what I understand about reference in C++ is correct.
Let's say we have
vector<int> a;
// add some value in a
vector<int> b = a; // 1. this will result another exact copy of inclusive of a's item to be copied in b right?
vector<int> &c = a; // 2. c will reference a right? c and a both "point"/reference to a copy of vector list right?
vector<int> &d = c; // 3. d will reference c or/and a right? now a, c, d all reference to the same copy of variable
vector<int> e = d; // 4. e will copy a new set of list from d right (or you can say a or c)?
Thanks.
You're correct, b is a distinct copy of a, a/c/d are all the same thing, just accessible via different names.
And e is a copy of a/c/d.
If you duplicate that code using the int type rather than a vector, you can see by the addresses what's happening under the covers:
#include <iostream>
int main() {
int a = 7, b = a, &c = a, &d = a, e = d;
std::cout << "a # " << &a << '\n';
std::cout << "b # " << &b << '\n';
std::cout << "c # " << &c << '\n';
std::cout << "d # " << &d << '\n';
std::cout << "e # " << &e << '\n';
return 0;
}
The output of that is:
a # 0xbfaff524
b # 0xbfaff520
c # 0xbfaff524
d # 0xbfaff524
e # 0xbfaff51c
and you can see that a, c and d all have the same address while b and e are distinct.
Yep, looks right.
If you add elements to c or d, the new elements will also be reflected in a.
If you add elements to e, then only e will have them.