Default positional arguments in C++11 templates - c++

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;
}

Related

c++11 - zero-initi of members insted of default-init

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
}

Why is this ranged based for loop causing issues with subtraction?

I'm having an issue with a ranged based for loop causing my values to go negative, and I've resolved the issue with a regular for loop but want to understand why it messed up in the first place. You can see from the sample output below that the initial values exist correctly, but then when attempting to subtract from them, they get reset to a default initialized value of 0 I guess?
Broken code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE IS IN THE LOOP BELOW
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i] = multRank[i] - 1;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Maximum Score from Performing Multiplication Operations\n";
test1();
}
Broken code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
-1-2-1
multRank after: -2 -1 0
Repaired code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE WAS IN THE LOOP BELOW
for (auto i = 0; i < multipliers.size(); ++i) {
multRank[i] = multipliers.size();
std::cout << " " << multRank[i];
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i]--;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Calculate Rank\n";
test1();
}
Repaired code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
212
multRank after: 1 2 3
The first range based for loop is not using references:
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
In this loop, n is a copy of the data in multRank. If you want to be able to modify the data in multRank, you want n to be a reference:
for (int& n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}

Pseudocode to actual code of linear fibonacci

We are trying to convert this pseudocode into an actual code. The pseudo code is
Algorithm LinearFibonacci(k):
Input: A nonnegative integer k
Output: Pair of Fibonacci numbers (Fk,Fk−1)
if k ≤ 1 then
return (k,0)
else
(i, j)← LinearFibonacci(k−1)
return (i+ j, i)
I tried to translate it and came up with this
pair<int,int> LinearFibonnaci(int k) {
int i = 0;
int j = 0;
if (k <= 1) {
return make_pair(k, 0);
}
else {
make_pair(i, j) = LinearFibonnaci(k - 1);
return make_pair(i + j, i);
}
}
Am i doing this corretly because im not sure how to print out a pair function?
A std::pair object (not function) has two public members, first and second.
Since C++11, you can also extract an element from a pair using std::get.
See the following examples (testable here):
#include <iostream>
#include <utility>
#include <tuple>
std::pair<int, int> LinearFibonnaci(int k);
int main()
{
int k = 3;
// Explicitly declaring the type
std::pair<int, int> f = LinearFibonnaci(k);
// ^^^^^^^^^^^^^^^^^^^
std::cout << "F(" << k << ") = "
<< f.first << ", F(" << (k - 1) << ") = " << f.second << '\n';
// ^^^^^^^ ^^^^^^^^
k = 4;
// Since C++11: Using 'auto' let the compiler deduce the type
auto g = LinearFibonnaci(k);
// ^^^^
std::cout << "F(" << k << ") = "
<< g.first << ", F(" << (k - 1) << ") = " << g.second << '\n';
// ^^^^^^^ ^^^^^^^^
k = 5;
// Since C++17: Structured binding declaration
// See e.g. https://en.cppreference.com/w/cpp/language/structured_binding
auto [n, m] = LinearFibonnaci(k);
// ^^^^^^^^^^^
std::cout << "F(" << k << ") = " << n << ", F(" << (k - 1) << ") = " << m << '\n';
// ^^^ ^^^
k = 8;
// Since C++11: std::tie
// See e.g. https://en.cppreference.com/w/cpp/utility/tuple/tie
std::tie(n, m) = LinearFibonnaci(k);
// ^^^^^^^^^^^^^^
std::cout << "F(" << k << ") = " << n << ", F(" << (k - 1) << ") = " << m << '\n';
// ^^^ ^^^
k = 12;
// Since C++11: std::get
// https://en.cppreference.com/w/cpp/utility/pair/get
auto h = LinearFibonnaci(k);
std::cout << "F(" << k << ") = " << std::get<0>(h)
// ^^^^^^^^^^^^^^
<< ", F(" << (k - 1) << ") = " << std::get<1>(h) << '\n';
// ^^^^^^^^^^^^^^
}
std::pair<int, int> LinearFibonnaci(int k)
{
int i = 0;
int j = 0;
if (k <= 1) {
return {k, 0}; // You can use the constructor, here
}
else {
std::tie(i, j) = LinearFibonnaci(k - 1);
return {i + j, i};
}
}
As this question is marked C++17, structured bindings (auto[i,j]) can be used.
Another thing is that by using curly braces we can directly initialize the std::pair return object.
std::pair<int,int> LinearFibonnaci(int k) {
if (k <= 1)
{
return {k, 0};
}
else
{
auto[i, j] = LinearFibonnaci(k - 1);
return {i + j, i};
}
}
To get the result, again structured bindings can be used to retrieve the values:
auto[i, j] = LinearFibonnaci(x);

How to reset a static struct inside a function

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.

Generically print a sequence of variables with their names

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