std::compare_exchange int with #define value - c++

I want to use std::compare_exchange_strong for some std::atomic<int>
For compilation reasons (int &) I am forced to introduce int _OLD_VALUE = OLD_VALUE.
Is there a more elegant way to achieve this?
Here is my example
#include <atomic>
#include <stdio.h>
#define OLD_VALUE 16
#define NEW_VALUE 744
#define OTHER_VALUE 80
int main(int argc, char **argv)
{
std::atomic<int> i(OTHER_VALUE);
int _OLD_VALUE = OLD_VALUE;
bool status = i.compare_exchange_strong(_OLD_VALUE,NEW_VALUE);
// bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
}
And here is the compilation error when I use the commented version:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:11:65: error: cannot bind non-const lvalue reference of type ‘std::__atomic_base<int>::__int_type& {aka int&}’ to an rvalue of type ‘int’
bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
^
In file included from /usr/include/c++/7/atomic:41:0,
from main.cpp:1:
/usr/include/c++/7/bits/atomic_base.h:496:7: note: initializing argument 1 of ‘bool std::__atomic_base<_IntTp>::compare_exchange_strong(std::__atomic_base<_IntTp>::__int_type&, std::__atomic_base<_IntTp>::__int_type, std::memory_order) [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]’
compare_exchange_strong(__int_type& __i1, __int_type __i2,
^~~~~~~~~~~~~~~~~~~~~~~

No. The reason being is that the previous value of the variable is exchanged so the expected value is overwritten if the compare mismatches.
To see what's going on under the hood, look at the GCC built-ins:
https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
You will note there is a __atomic_exchange_n in the builtins for GCC (Linux) but that simply provides an exchange as opposed to a compare-and-swap. The Windows equivalent is InterlockedExchange : https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-interlockedexchange
For the sake of readability I would avoid using capitals in variable names and avoid leading underscores:
int oldValue = OLD_VALUE;

The simplest way (and I suppose the only way) to achieve this is to just write simple wrapper:
bool cas_strong(std::atomic<int>& a, int cmp, int exc) {
return a.compare_exchange_strong(cmp, exc);
}

compare_exchange_strong expects an int& to store the current value found in i. Here, you provide indirectly 16 (that is what your macro OLD_VALUE is replaced with at pre-processing), which is an integer compile-time constant, a.k.a. constexpr int&. This is not compatible with int&.
To provide an int&, you should better keep an int near your call of compare_exchange_strong:
std::atomic<int> i(OTHER_VALUE);
int old_value = OLD_VALUE;
bool status = i.compare_exchange_strong(old_value, NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
Also, more generally, it is clearly more powerful if you used static constants instead of macros here.
More on this in this other question: What is the difference between a macro and a const in C++?

Don't use macros to define the values:
#include <atomic>
#include <stdio.h>
int OLD_VALUE 16
int NEW_VALUE 744
int OTHER_VALUE 80
int main(int argc, char **argv)
{
std::atomic<int> i(OTHER_VALUE);
bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
}

Related

comparison of integer expressions of different signedness: correct way of using "for" loop when handling string type

below is c++ code. And I am getting these warnings when compile
comparison of integer expressions of different signedness: ‘int’ and ‘std::__cxx11::basic_string::size_type’ {aka ‘long unsigned int’} [-Werror=sign-compare]
15 | for(int x=0; x<s.length();x++)
~^~~~~~~~~~~
different signedness means that I am comparing long unsigned int which is 64 bits to int (which should be 32 bit) I did not know.. that string.length returns that type. So my question is how to write these simple instructions in c++ without any error showing when compiled with -Wall -Werror
I also get following error message. I supposed string class is in namespace std so the question is: when do we get this error and what that error tells. I think its saying that my program uses only namespace which is std so its not required to do std:string s to create a variable . this removes the error string s without namespace. is this correct thinking or is there any other meaning too
f.cpp:7:1: error: label ‘std’ defined but not used [-Werror=unused-label]
7 | std:string s="hello";
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
string s="hello";
char c[s.length()-1];
s[1]='b';
char d='x';
s.push_back(d);
s+='x';
strcpy(c,s.c_str());
for(int x=0; x<s.length();x++)
{
cout<<c[x];
}
}
Because str.length() returns long unsigned int rather than int, casting it as an int should prevent it from giving an warning or error.
Instead of
std::string str = "Test";
for (int i = 0; i < str.length(); i++) {
something(str[i]);
}
Try
std::string str = "Test";
for (int i = 0; i < (int) str.length(); i++) {
something(str[i]);
}

C++ Function calling fails

I get the following error when declaring a function:
Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp:23:5: error: no matching function for call to 'printstats'
printstats(&x, y);
^~~~~~~~~~
/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp:10:6: note: candidate function not viable: no known conversion from 'const std::string *' (aka 'const basic_string<char, char_traits<char>, allocator<char> > *') to 'const std::string' (aka 'const basic_string<char, char_traits<char>, allocator<char> >') for 1st argument; remove &
void printstats(const std::string& x, int statnum);
^
/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp:12:6: note: candidate function not viable: no known conversion from 'const std::string *' (aka 'const basic_string<char, char_traits<char>, allocator<char> > *') to 'char *' for 1st argument
void printstats(char * x, int stat_num)
^
1 error generated.
[Finished in 0.9s with exit code 1]
[shell_cmd: g++ "/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example.cpp" -o "/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example" && "/Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++/c++example"]
[dir: /Users/masterprogrammer/PycharmProjects/WolvesBatsRocks/c++]
[path: /anaconda3/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin]
The function takes two inputs and I am calling it from main.
I am expecting an output which has the following formatting Strength: 7.
Here is the code:
// C program to illustrate
// call by value
#include <stdio.h>
#include <iostream>
#include <ctime> // For time()
#include <cstdlib> // For srand() and rand()
#include <string>
#include <cstring>
void printstats(const std::string& x, int statnum);
void printstats(char * x, int stat_num)
{
printf("%s: %d", x, stat_num);
}
int main(void)
{
const std::string&x = "Strength";
int y = 7;
// Passing parameters
printstats(&x, y);
return 0;
}
Your function prototype void printstats(const std::string& x, int statnum) and function definition void printstats(char * x, int stat_num) expect different parameters.
One expects a const string & as the first parameter and the other expects a char * as the first parameter.
Change both to have the same parameters and make sure your function call passes the appropriate argument(s) to the function.
You can't define an address type, but instead you can pass addresses of other variables which I think neither is what you're aiming to do.
& in method signature means call by reference which basically means inside the function the reference is used to access the actual argument used in the call.
To make it work, define a string and pass it directly.
std::string x= "Strength";
int y = 7;
printstats(x, y);
You really need to read a good introductory C++ book. It seems that you took an example from a C book, and tried to use it in C++ without understanding of what's happening.
I removed the unnecessary includes:
#include <stdio.h>
#include <string>
//Use a reference to string object instead of char pointer
void printstats(const std::string& x, int stat_num)
{
//printf is a C function that expects a C char* straing,
//so we need to convert the C++ string into it
printf("%s: %d", x.c_str(), stat_num);
}
int main(void)
{
//no need for "&" here - it's totally incorrect.
//It is an operation of taking an address of a variable.
const std::string x = "Strength";
int y = 7;
//no need for & here too
printstats(x, y);
return 0;
}
Output:
Strength: 7

Can we send pair a template argumrent another pair

Can we use pair as an argument for another pair in C++.
Here is a test program to do that.
#include <iostream>
#include <utility>
int main()
{
std::pair<int,int> m;
m=std::make_pair(1,3);
int r = 3;
int *q = &r;
int **p =&q;
int **t = p;
std::pair<int**,<std::pair<int,int> > > i(p,m);
std::cout<<i[t];
return 0;
}
This is the error, I am getting.
Test.cpp: In function ‘int main()’:
Test.cpp:12:45: error: template argument 2 is invalid
std::pair<int**,<std::pair<int,int>>> i(p,m);
^
If I changed the format of declaration and wrote the program in the following way,
#include <iostream>
#include <utility>
int main()
{
std::pair<int,int> m;
m=std::make_pair(1,3);
int r = 3;
int *q = &r;
int **p =&q;
int **t = p;
std::pair<
int**,
<
std::pair<
int,
int
>
>
> i(p,m);
std::cout<<i[t];
return 0;
}
There is an additional error.
Test.cpp: In function ‘int main()’:
Test.cpp:20:7: error: template argument 2 is invalid
> i(p,m);
^
Test.cpp:20:14: error: expression list treated as compound expression in initializer [-fpermissive]
> i(p,m);
What might be the issue and how to solve it?
On a side note, I did a program and compiled it in an very old Dev-c++ compiler on a windows 7 machine which used a code similar to the above and it ran perfectly fine. It was a lab program in my college which had only that compiler.
The above code, I ran on both windows 7 and Ubuntu 16.04 using GNU g++ 5.4.0
Ideone: Link to the actual program for reference
You might also have a look at the actual error, I faced in the above link.
This is incorrect:
std::pair<int**,<std::pair<int,int> > > i(p,m);
Just remove the extra <>:
std::pair<int**, std::pair<int,int > > i(p,m);
Also, I'm not sure what you're trying to do in the cout part, but pair doesn't have a [] operator. You can access the elements with first and second:
i.first
i.second
i.second.first
i.second.second
You may also be interested in std::tuple if you don't want to nest one pair into another:
std::tuple<int**, int, int> i;
There are two problems with your code.
You have a superfluous pair of angle brackets in your template instantiation.
The cout parameter makes no sense
#include <iostream>
#include <utility>
int main()
{
std::pair<int,int> m;
m=std::make_pair(1,3);
int r = 3;
int *q = &r;
int **p =&q;
int **t = p;
std::pair<
int**,
// < Omit this
std::pair<
int,
int
>
// > also this
> i(p,m);
// std::cout<<i.[t]; indexing with a pointer value doesn't make sense
// i. for a pair doesn't make sense, specify either first or second
std::cout<<i.first[0]; // <<<< Did you mean something like this?
return 0;
}
Check the compiling version live

C++ placement new keep giving compiling error

Try to use placement new but it kept giving me errors. I remember a while ago, it was working. g++ (ver 4.8.4) on Ubuntu 14.04.
#include <stdio.h>
typedef unsigned int uint;
struct strSession {
uint sessionId;
uint srcIp;
uint dstIp;
};
int main(int argc, char *argv[]) {
char buf[20];
strSession *q = (strSession*)&buf[0];
new (q) strSession;
return 0;
}
Got error
$ g++ -std=c++11 te.cc `pkg-config --cflags glib-2.0`
te.cc: In function ‘int main(int, char**)’:
te.cc:12:10: error: no matching function for call to ‘operator new(sizetype, strSession*&)’
new (q) strSession;
^
te.cc:12:10: note: candidate is:
<built-in>:0:0: note: void* operator new(long unsigned int)
<built-in>:0:0: note: candidate expects 1 argument, 2 provided
Any idea what's wrong?
To use placement new, you need to have:
#include <new>
Also, you could just as easily have used:
int main(int argc, char *argv[]) {
char buf[20];
strSession *q = new (buf) strSession;
return 0;
}
To make your original code work, you need to add
void* operator new( size_t, strSession * p ) { return p; }
In the old days, before C++ left Bell Labs, C++ had a feature where
a constructor could assign to 'this'. The operator new placement
syntax was considered an improvement.

Why does g++ 4.8.1 issue a conversion warning

When I compile the code below with g++ 4.8.1 (64bit) in this way:
$ g++ -Wconversion -o main main.cpp
I get this result:
main.cpp: In function ‘int main()’:
main.cpp:12:20: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value [-Wconversion]
int i = sizeof(x)/sizeof(x[0]);
^
My expectation would be that the compiler should be able to evaluate the expression at compile time. If you make a similar program in plain c, gcc works like a charm.
Should this be considered a bug in g++ (e.g. clang++ does not have this problem)?
if you change the problematic line to something like:
char c = 0x10000000/0x1000000;
then the compiler does not complain. This suggest that some constant evaluation is done before warning generation.
main.cpp:
#include <iostream>
struct foo {
int a;
int b;
};
foo x[50];
int main()
{
int i = sizeof(x)/sizeof(x[0]);
std::cout << i << std::endl;
return 0;
}
int i = sizeof(x)/sizeof(x[0]);
//int <-- std::size_t <-- std::size_t / std::size_t
The type of the expression sizeof(x)/sizeof(x[0]) is std::size_t which on your machine is unsigned long int. So conversion from this type to int is data-loss, if the source is bigger in size than the target.
Though, I agree that in your case, there would not be actual data-loss if the compiler actually computes the value, but I guess it applies -Wconversion before the actual computation.
sizeof() returns you std::size_t not int! So cast it or declare i as std::size_t.
std::size_t i = sizeof(x)/sizeof(x[0]);