I would like to:
int a = 2;
int b = 3;
// ...
PRINT1(a, b, ...);
PRINT2(a, b, ...);
where PRINT1 should expand to:
std::cout << "a = " << a << ", b = " << b << ... << std::endl;
// note: in "a = ...", "a" is the name of the variable, i.e.:
// PRINT(bar, ...) should print "bar = ..."
and PRINT2 should expand to (using cppformat):
fmt::print("a = {}, b = {}, ...", a, b, ...);
Right now i'm using the Boost.PP and have to write PRINT((a)(b)(c)...) to achieve something similar to the first scenario, but it would be better if I could just use commas instead. A solution to one of the problems can probably be easily adapted to solve both.
You can use BOOST_PP_TUPLE_TO_SEQ to convert it to a sequence, like so:
#define PRINT_ARGS(...) PRINT(BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__)))
Here is my solution. Not very dynamic, you have to know beforehand how many arguments you are going to have:
// Using macros:
#define PRINT1_1(A) std::cout << "a = " << A << std::endl;
#define PRINT1_2(A,B) std::cout << "a = " << A << ", b = " << B << std::endl;
#define PRINT2_1(A) fmt::print("a = {}", A);
#define PRINT2_2(A,B) fmt::print("a = {}, b = {}", A, B);
// Using `va_arg`:
#include <iostream>
#include <cstdarg>
void PRINT1(int argc, ...)
{
va_list args;
va_start(args, argc);
char vc = 'a';
int val = argc;
for (int i = 0; i < argc; ++i, ++vc) {
std::cout << vc << " = " << va_arg(args, int);
if (i < argc - 1)
std::cout << ", ";
}
va_end(args);
std::cout << std::endl;
}
// similarly implement PRINT2
int main()
{
PRINT1_2(1,2);
// first argument specifies the number
// of the remaining arguments:
PRINT1(3, 1,2,4);
return 0;
}
Output:
a = 1, b = 2
a = 1, b = 2, c = 4
Related
In the below code, I expect members of a being inited with gargabe as they are not mentioned in the members-init-list of the called constructor (with two int parameters). Instead, I'm constantly getting 0 in both i and j of a, b and c and I am failing to see why. Could anybody please point me in the right direction?
#include <iostream>
#include <type_traits>
class A {
public:
int i;
int j;
A() = delete;
A(int a, int b) { std::cout << "VOLOLO!" << std::endl; };
};
int
smear_stack(int p)
{
int j = p++;
int a[500] = {};
for(int i = 0; i < 499; i++) {
a[i] = ++j;
}
std::cout << j << std::endl;
return ++j;
}
int main(void)
{
int i = 2;
i = smear_stack(++i);
A a (i, 32 );
std::cout << "a is " << a.i << " " << a.j << std::endl;
A b = { a };
std::cout << "b is " << b.i << " " << b.j << std::endl;
A c = { a.i, a.j };
std::cout << "c is " << c.i << " " << c.j << std::endl;
}
The i and j fields that you are accessing are, indeed, uninitialized. However, you are smearing the wrong part of the stack. It just so happens that on most OSes, the stack is initially all zeros. It even used to be common in C (long ago) to assume that automatic variables in main were zero-initialized.
To see that the memory is indeed uninitialized, it suffices to put something else there. Here's an example:
#include <iostream>
#include <memory>
class A {
public:
int i;
int j;
A() = delete;
A(int a, int b) { std::cout << "VOLOLO!" << std::endl; };
};
union U {
int is[2];
A a;
U() : is{3,4} {}
};
int
main()
{
U u;
std::construct_at(&u.a, 5, 6);
std::cout << u.a.i << ", " << u.a.j << std::endl;
// output:
// VOLOLO!
// 3, 4
}
This question already has answers here:
C++, variable declaration in 'if' expression
(8 answers)
Closed 3 years ago.
I wanted to be able to do multiple assignments in an if block and short-circuit if the first one fails. However, this does not compile and says, expected primary-expression before ‘auto’
#include <iostream>
#include <optional>
std::optional<int> foo()
{
return 0;
}
int main() {
if (auto a = foo() && auto b = foo())
{
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
}
The following works though and does what I want.
if (auto a = foo())
{
if (auto b = foo()) {
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
}
But is there a way for me to use the syntax in the first one? Using parenthesis to surround the expressions does not work.
Since C++17, you could write
if (decltype(foo()) a, b; (a = foo()) && (b = foo()))
{
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
But if you want to see the short circuit in action, you should change the condition:
#include <iostream>
#include <optional>
std::optional<int> foo()
{
std::cout << "foo called.\n";
return 1;
}
int main()
{
if (decltype(foo()) a, b; (a = foo()) or (b = foo()))
{
// For exposition only ^^
std::cout << "a = " << *a << ", b = " << *b << std::endl;
// Note that, now, this is UB ^^
}
}
Compare the output of this
foo called.
a = 1, b = 0
Versus the former.
It has nothing to do with auto. Declarations cannot be part of an expression. You can either use an expression or a single declaration inside an if statement.
So even this will not compile:
#include <iostream>
int foo()
{
return 0;
}
int main()
{
if (int a = foo() && int b = foo())
{
std::cout << "a = " << a << ", b = " << b << std::endl;
}
return 0;
}
Edit: In C++17 you can have an initializer statement before the condition statement, like so: if (auto a = foo(), b = foo(); a && b). However that will not give you short circuiting.
The only way I see is that you reformulate (without declaring the variables inside the if condition):
#include <iostream>
#include <optional>
std::optional<int> foo()
{
return 0;
}
int main() {
std::optional<int> a , b;
if ((a = foo()) && (b = foo()))
{
std::cout << "a = " << *a << ", b = " << *b << std::endl;
}
}
See a working example here please.
Since c++17 you can even do the variable declarations inside the if condition like this:
if (std::optional<int> a , b; (a = foo()) && (b = foo()))
Though usage of auto isn't possible in that case.
Another live demo.
If static variables has only one copy for the program. So why is it not possible to swap 2 numbers using another function?
Code:
#include <iostream>
void swap(int, int);
int main()
{
static int a = 1;
static int b = 2;
swap(a, b);
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
std::cin.get();
}
void swap(int a,int b)
{
int temp = a;
a = b;
b = temp;
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
}
As the 'swap' function is taking parameters as pass by value, copies of the variables are passed to the swap function which will only swap its local variables 'a' and 'b' (passed as parameter) not the static ones passed from main.
Swap should be taking parameters as references like below.
#include <iostream>
void swap(int&, int&);
int main()
{
static int a = 1;
static int b = 2;
swap(a, b);
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
std::cin.get();
}
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
}
Please note that static variable defined in a function pertains its value in the subsequent calls of the function in which it is declared.
This is because you are passing arguments by value and not by address(reference). Your function is working on a copy of a and a copy of b - not the original values. You could try this(notice the & in the function prototype and function definition arguments)
void swap(int &, int &);
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
std::cout << "a = " << a << std::endl << "b = " << b << std::endl;
}
So let's say I have a function
struct coinTypes {
int tenP = 0;
int twentyP = 0;
int fiftyP = 0;
};
coinTypes numberOfCoins(int coins)
{
static coinTypes types;
// incrementing structs values
}
Let's say I have used this function for some time, and values in coinTypes struct are no longer 0. Then I decided to use this function for another purpose and I need the values to be 0 again. Is there any way to reset coinTypes struct?
Unless you are just misunderstanding what the keyword static does (you probably are), this is what you are asking for:
run online
#include <iostream>
struct britishCoins {
int tenP;
int twentyP;
int fiftyP;
};
britishCoins& getCoins () {
static britishCoins coins {0, 0, 0};
return coins;
}
void resetCoins () {
getCoins() = {0, 0, 0};
}
britishCoins numberOfCoins(int coins)
{
britishCoins& result = getCoins();
result.tenP += coins / 10;
//...
return result;
}
int main () {
std::cout << numberOfCoins(0).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
resetCoins();
std::cout << numberOfCoins(0).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
std::cout << numberOfCoins(10).tenP << std::endl;
return 0;
}
Prints:
0
1
2
3
4
0
1
2
3
4
If you just want to convert int coins into britishCoins without storing it's value inside the function it's simple:
run online
#include <iostream>
struct britishCoins {
int tenP;
int twentyP;
int fiftyP;
};
britishCoins numberOfCoins(int coins)
{
britishCoins result;
result.fiftyP = coins / 50;
coins %= 50;
result.twentyP = coins / 20;
coins %= 20;
result.tenP = coins / 10;
return result;
}
int main () {
for (int i = 0; i < 3; ++i) {
britishCoins coins = numberOfCoins(130);
std::cout << coins.fiftyP << "*50 + " << coins.twentyP << "*20 + " << coins.tenP << "*10" << std::endl;
}
return 0;
}
output:
2*50 + 1*20 + 1*10
2*50 + 1*20 + 1*10
2*50 + 1*20 + 1*10
Dont use static in this case. Try to use:
Class Coin with object params coinType, couinNumber for example.
It's allowed to leave template arguments blank (using <>), how would you leave a positional argument blank or rework this to achieve the same effect.
template <int i = 0, int j = 1, int k = 2>
void blah() {
std::cout << i << " " << j << " " << k << std::endl;
}
int main() {
blah(); // ok
blah<>(); // ok
blah<1>(); // ok, i = 1
blah<1,,3>(); // not ok, i = 1, j = 1 (default), k = 3
return 0;
}
It is not possible to do this. You have to pass it.
Here is a suggestion:
auto constexpr default_j = 1;
template <int i = 0, int j = default_j, int k = 2>
void blah() {
std::cout << i << " " << j << " " << k << std::endl;
}
int main() {
blah(); // ok
blah<>(); // ok
blah<1>(); // ok, i = 0
blah<1, default_j, 3>(); // ok, explicit and without duplicate magic numbers!
return 0;
}
Fun with macros (do not try this at home, kids):
#include <iostream>
template <int i = 0, int j = 1, int k = 2>
void blah() {
std::cout << i << " " << j << " " << k << std::endl;
}
#define _blah(D, V) (*#V ? V + 0 : D)
#define blah_3(I,J,K) blah<_blah(0,I), _blah(1,J), _blah(2,K)>()
#define blah_2(I,J) blah_3(I,J,)
#define blah_1(I) blah_3(I,,)
#define blah__(_1,_2,_3,X,...) blah ## X
#define blah(...) blah__(__VA_ARGS__,_3,_2,_1)(__VA_ARGS__)
int main() {
blah();
blah(, ,);
blah(1);
blah(1,,);
blah(1, ,3);
return 0;
}