why this PP_ARG_COUNT macro need a PP_EXPAND? - c++

#include <type_traits>
#include <iostream>
using namespace std;
// Expand
#define PP_EXPAND(X) X
// Counter Arguments count
#define PP_ARG_COUNT(...) PP_EXPAND( PP_ARG_POPER(__VA_ARGS__, 5, 4, 3, 2, 1, 0) )
#define PP_ARG_COUNT2(...) PP_ARG_POPER(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define PP_ARG_POPER(_1, _2, _3, _4, _5, N, ...) N
int main()
{
cout << PP_ARG_COUNT(1, 2, int) << endl;
cout << PP_ARG_COUNT2(1, 2, int) << endl;
cout << PP_ARG_POPER(1, 2, int, 5, 4, 3, 2, 1 0) << endl;
return 0;
}
i have compile this code under visual studio 2013, it output:
3
1
3
why this macro need a PP_EXPAND, and PP_ARG_COUNT2 it not work well?

This is a workaround for a bug in the Visual C++ preprocessor. It incorrectly fails to expand comma-delimited token sequences in some contexts.
In your PP_ARG_COUNT2, the __VA_ARGS__ is treated as a single argument when used in the invocation of PP_ARG_POPER, causing the incorrect result.
The most common workaround for this issue is to introduce an additional layer of indirection that forces the compiler to reevaluate the comma-delimited token sequence. The technique used here, with PP_ARG_COUNT invoking through EXPAND is one way to do this; I presented a variation on this technique in an answer to another question.

Related

C++ Preprocessor macro selection by argument

I'm trying to define a preprocessor macro that in turn selects the right macro depending on the value of an argument.
#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
#define BIT(n) ?????
int main() {
printf("%d %s", BIT(9));
return 0;
}
BIT(n) should expand to:
BIT_8(n) if n≤8
BIT_N(n) if n>8
Any way to achieve this?
Unless you want very clumsy code, you can't do that. The preprocessor has no idea about the value of the argument passed in. It's just doing string replacement and that's all.
That being said, they are crazy guys implementing BIT_x for all x in [0 to 63].
This is very ugly and would fail is used with an argument set at 64.
A clean solution is to use a function instead:
const char * bit_msg(unsigned int b)
{
if (b > 8) return "is greater than 8";
const char * bits[] = {
"is 0 and lower than 8",
"is 1 and lower than 8",
"is 2 and lower than 8",
"is 3 and lower than 8",
"is 4 and lower than 8",
"is 5 and lower than 8",
"is 6 and lower than 8",
"is 7 and lower than 8",
"is 8",
};
return bits[b];
}
#define BIT(X) X, bit_msg(X)
[...]
printf("%d %s", BIT(9));
Because you've tagged the question with C++ and to follow #Romen you could achieve similar result using constexpr that, if possible, will be computed by the compiler at compile time, resulting in code that's as efficient as a macro.
In the example above, you'll just need to replace the signature with constexpr const char * bit_msg(unsigned int b) and the compiler might even skip the function and write (the equivalent of) printf("%d %s", 9, "is greater than 8").
The challenge is that the pre-processor doesn't know math. You can solve this problem by implementing the math you need, but it gets UGLY. For example, here's working pre-processor code for what you want to do:
#include <stdio.h>
#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
// Identify values less than 8; make the second argument 8
#define LT_8_0 ~,8
#define LT_8_1 ~,8
#define LT_8_2 ~,8
#define LT_8_3 ~,8
#define LT_8_4 ~,8
#define LT_8_5 ~,8
#define LT_8_6 ~,8
#define LT_8_7 ~,8
#define LT_8_8 ~,8
// Helper macros. Delays let arguments be processed before the macros is run.
#define MERGE(A, B) A ## B
#define MERGE_DELAY(A, B) MERGE(A,B)
#define ARG2(A,B,...) B
#define ARG2_DELAY(A,B,...) ARG2(A,B,__VA_ARGS__)
// Return 8 or N depending if n <= 8...
#define LT_8(n) ARG2_DELAY( MERGE(LT_8_, n), N,~ )
#define BIT(n) MERGE_DELAY(BIT_, LT_8(n))(n)
int main() {
printf("%d %s\n", BIT(9));
return 0;
}
Note that the LT_8 macro works by taking the second of a series of arguments. We default that second argument to N, but if we recognize the input number to be 8 or less, we insert a new second argument of 8.
you could do this
#include <stdio.h>
#define BIT_8(n) printf("%d is lower than or equal to 8 \n" , n)
#define BIT_N(n) printf("%d is greater than 8 \n" , n)
#define BIT(n) ((n <= 8) ? (BIT_8(n)) : (BIT_N(n)))
int main() {
BIT(7);
BIT(8);
BIT(9);
return 0;
}

How to exit std.algorithm.iteration.reduce prematurely?

I have the following function findFirstDuplicateFrequency that implements (correctly) an algorithm for a programming puzzle.
Instead of imperative looping I'd like to promote D's functional features and thought I can apply reduce to the problem.
I run into an issues that I need to be able to iterate the input sequence multiple (but unknown) times and quit the processing when the exit condition is met.
AFAICS the standard reduce can't be exited in the middle of the processing and I also struggle how to carry on extra accumulator information that is used to calculate the exit condition.
So what would be the correct (?) idiomatic D approach to solve the problem in a (more) functional way ?
This is my very first D program ever and so all other comments are welcome too !
import std.conv: to;
/**
From: https://adventofcode.com/2018/day/1
You notice that the device repeats the same frequency change list over and
over. To calibrate the device, you need to find the first frequency it reaches
twice.
For example, using the same list of changes above, the device would loop as
follows:
Current frequency 0, change of +1; resulting frequency 1.
Current frequency 1, change of -2; resulting frequency -1.
Current frequency -1, change of +3; resulting frequency 2.
Current frequency 2, change of +1; resulting frequency 3.
(At this point, the device continues from the start of the list.)
Current frequency 3, change of +1; resulting frequency 4.
Current frequency 4, change of -2; resulting frequency 2, which has already been seen.
In this example, the first frequency reached twice is 2. Note that your device
might need to repeat its list of frequency changes many times before a
duplicate frequency is found, and that duplicates might be found while in the
middle of processing the list.
Here are other examples:
+1, -1 first reaches 0 twice.
+3, +3, +4, -2, -4 first reaches 10 twice.
-6, +3, +8, +5, -6 first reaches 5 twice.
+7, +7, -2, -7, -4 first reaches 14 twice.
What is the first frequency your device reaches twice?
*/
int findFirstDuplicateFrequency(int[] frequencyChanges)
pure
{
int[int] alreadySeen = [0:1];
int frequency = 0;
out_: while(true) {
foreach(change; frequencyChanges) {
frequency += change;
if (int* _ = frequency in alreadySeen) {
break out_;
} else {
alreadySeen[frequency] = 1;
}
}
}
return frequency;
} unittest {
int answer = 0;
answer = findFirstDuplicateFrequency([1, -2, 3, 1]);
assert(answer == 2, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequency([1, -1]);
assert(answer == 0, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequency([3, 3, 4, -2, -4]);
assert(answer == 10, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequency([-6, 3, 8, 5, -6]);
assert(answer == 5, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequency([7, 7, -2, -7, -4]);
assert(answer == 14, "Got: " ~ to!string(answer));
}
void main() {}
Even according to #AdamD.Ruppe there is no great hopes to make the code more "functional" I was inspired by #BioTronic's cumulativeFold + until hint and decided to have a second look.
Unfortunately I see no way to apply cumulativeFold + until as I don't have a sentinel value required by until and there is still the same stopping problem than with reduce.
When I was browsing standard runtime library reference I noticed each do have an early exit (aka partial iteration) option. I also run into std.range.cycle.
Combining these two shiny new things I came to the solution below. findFirstDuplicateFrequencyV2 uses cycle and each to replace the imperative loops of the first version. I'm not sure if this version is any simpler but hopefully it is more "trendy" !
int findFirstDuplicateFrequencyV2(int[] frequencyChanges)
pure
{
import std.algorithm.iteration : each;
import std.range : cycle;
import std.typecons : Yes, No;
int[int] alreadySeen = [0:1];
int frequency = 0;
frequencyChanges.cycle.each!((change) {
frequency += change;
if (frequency in alreadySeen) {
return No.each;
}
alreadySeen[frequency] = 1;
return Yes.each;
});
return frequency;
} unittest {
import std.conv : to;
int answer = 0;
answer = findFirstDuplicateFrequencyV2([1, -2, 3, 1]);
assert(answer == 2, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequencyV2([1, -1]);
assert(answer == 0, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequencyV2([3, 3, 4, -2, -4]);
assert(answer == 10, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequencyV2([-6, 3, 8, 5, -6]);
assert(answer == 5, "Got: " ~ to!string(answer));
answer = findFirstDuplicateFrequencyV2([7, 7, -2, -7, -4]);
assert(answer == 14, "Got: " ~ to!string(answer));
}

Accepting random number of inputs cpp [duplicate]

This question already has answers here:
Variable number of arguments in C++?
(17 answers)
Closed 8 years ago.
I want to accept some inputs for a program,the inputs are integer values.
The condition on accepting the inputs is number of inputs is not fixed
but maximum number of inputs to be taken is fixed.
for example lets say the maximum input limit is 15 inputs.
So I should be able to accept "n" inputs where "n" can have any value from 1 to 15.
Is there a way to do this in cpp?
There is a general mechanism in C and C++ for writing functions that accept an arbitrary number of arguments. Variable number of arguments in C++?. However, this will not create a restriction on the number of args or restrict the overloads to a fixed type and it is generally a bit clunky to use (IMO).
It is possible to do something with variadic templates, for instance:
#include <iostream>
#include <vector>
using namespace std;
void vfoo(const std::vector<int> &ints)
{
// Do something with the ints...
for (auto i : ints) cout << i << " ";
cout << endl;
}
template <typename...Ints>
void foo(Ints...args)
{
constexpr size_t sz = sizeof...(args);
static_assert(sz <= 15, "foo(ints...) only support up to 15 arguments"); // This is the only limit on the number of args.
vector<int> v = {args...};
vfoo(v);
}
int main() {
foo(1);
foo(1, 2, 99);
foo(1, 4, 99, 2, 5, -33, 0, 4, 23, 3, 44, 999, -43, 44, 3);
// foo(1, 4, 99, 2, 5, -33, 0, 4, 23, 3, 44, 999, -43, 44, 3, 0); // This will not compile
// You can also call the non-template version with a parameter pack directly:
vfoo({4, 3, 9});
// Downside is that errors will not be great; i.e. .this
// foo(1.0, 3, 99);
// /Users/jcrotinger/Work/CLionProjects/so_variadic_int_function/main.cpp:21:22: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
// vector<int> v = {args...};
// ^~~~
// /Users/jcrotinger/Work/CLionProjects/so_variadic_int_function/main.cpp:38:5: note: in instantiation of function template specialization 'foo<double, int, int>' requested here
// foo(1.0, 3, 99);
// ^
return 0;
}
The static assert is the only thing that will limit this to 15 arguments. As the comment indicates, type checking is messy since the error message will come not from the function call but from the initialization of the vector.
This does require support for C++ 11's variadic templates.

C++ random number from a set

Is it possible to print a random number in C++ from a set of numbers with ONE SINGLE statement?
Let's say the set is {2, 5, 22, 55, 332}
I looked up rand() but I doubt it's possible to do in a single statement.
int numbers[] = { 2, 5, 22, 55, 332 };
int length = sizeof(numbers) / sizeof(int);
int randomNumber = numbers[rand() % length];
Pointlessly turning things into a single expression is practically what the ternary operator was invented for (I'm having none of litb's compound-statement trickery):
std::cout << ((rand()%5==0) ? 2 :
(rand()%4==0) ? 5 :
(rand()%3==0) ? 22 :
(rand()%2==0) ? 55 :
332
) << std::endl;
Please don't rat on me to my code reviewer.
Ah, here we go, a proper uniform distribution (assuming rand() is uniform on its range) in what you could maybe call a "single statement", at a stretch.
It's an iteration-statement, but then so is a for loop with a great big block containing multiple statements. The syntax doesn't distinguish. This actually contains two statements: the whole thing is a statement, and the whole thing excluding the for(...) part is a statement. So probably "a single statement" means a single expression-statement, which this isn't. But anyway:
// weasel #1: #define for brevity. If that's against the rules,
// it can be copy and pasted 7 times below.
#define CHUNK ((((unsigned int)RAND_MAX) + 1) / 5)
// weasel #2: for loop lets me define and use a variable in C++ (not C89)
for (unsigned int n = 5*CHUNK; n >= 5*CHUNK;)
// weasel #3: sequence point in the ternary operator
((n = rand()) < CHUNK) ? std::cout << 2 << "\n" :
(n < 2*CHUNK) ? std::cout << 5 << "\n" :
(n < 3*CHUNK) ? std::cout << 22 << "\n" :
(n < 4*CHUNK) ? std::cout << 55 << "\n" :
(n < 5*CHUNK) ? std::cout << 332 << "\n" :
(void)0;
// weasel #4: retry if we get one of the few biggest values
// that stop us distributing values evenly between 5 options.
If this is going to be the only code in the entire program, and you don't want it to return the same value every time, then you need to call srand(). Fortunately this can be fitted in. Change the first line to:
for (unsigned int n = (srand((time(0) % UINT_MAX)), 5*CHUNK); n >= 5*CHUNK;)
Now, let us never speak of this day again.
Say these numbers are in a set of size 5, all you gotta do is find a random value multiplied by 5 (to make it equi probable). Assume the rand() method returns you a random value between range 0 to 1. Multiply the same by 5 and cast it to integer you will get equiprobable values between 0 and 4. Use that to fetch from the index.
I dont know the syntax in C++. But this is how it should look
my_rand_val = my_set[(int)(rand()*arr_size)]
Here I assume rand() is a method that returns a value between 0 and 1.
Yes, it is possible. Not very intuitive but you asked for it:
#include <time.h>
#include <stdlib.h>
#include <iostream>
int main()
{
srand(time(0));
int randomNumber = ((int[]) {2, 5, 22, 55, 332})[rand() % 5];
std::cout << randomNumber << std::endl;
return 0;
}
Your "single statement" criteria is very vague. Do you mean one machine instruction, one stdlib call?
If you mean one machine instruction, the answer is no, without special hardware.
If you mean one function call, then of course it is possible. You could write a simple function to do what you want:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int setSize = 5;
int set[] = {2, 5, 22, 55, 332 };
srand( time(0) );
int number = rand() % setSize;
printf("%d %d", number, set[number]);
return 0;
}

C++ anonymous variables

Why won't this work?
0. #define CONCAT(x, y) x ## y
1.
2. #define VAR_LINE(x) \
3. int CONCAT(_anonymous, __LINE__) = x
4.
5. #define VAR_LINE2(x) \
6. int _anonymous ## x = 1
7.
8. int main()
9. {
10. VAR_LINE(1);
11. VAR_LINE(1);
12. VAR_LINE(1);
13. VAR_LINE2(__LINE__);
14. }
The result from the above macro expansion
int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous13 = 1;
It would be convenient if I didn't have to write that __LINE__ macro as an argument.
I'm thinking the problem is pretty clear. I want to be able to generate anonymous variables so that this macro doesn't fail with redefinition error when declaring several variables within the same scope. My idea was to use the predefined __LINE__ macro because no variable will ever be declared on the same line like this. But the macro expansion troubles me, can you help?
Update: Correct answer
Thanks to Luc Touraille. However, there was a tiny problem with the suggested solution. There has to be whitespace between the operands and the ## operator (apparently the standard says otherwise but the the PS3 flavoured GCC would not expand the macro properly if there were no whitespace between the operator and operands).
#define _CONCAT(x,y) x ## y
#define CONCAT(x,y) _CONCAT(x,y)
The VAR_LINE macro now yields:
int _anonymous10 = 1;
int _anonymous11 = 1;
int _anonymous12 = 1;
This has been verified to work under Win32 (Visual Studio 2008), XBOX360 (Xenon) and PS3.
You need to add a level of indirection so that __LINE__ will be expanded:
#define _CONCAT_(x,y) x ## y
#define CONCAT(x,y) _CONCAT_(x,y)
#define VAR_LINE(x) int CONCAT(_anonymous, __LINE__) = x