Passing defaulted/'optional' parameters to C++ functions by name - c++

I am new to c++ and trying to learn how to use the optional parameters in functions.
Right now I know that you can make a function with optional parameters like this:
void X_plus_Y(int x=10, y=20) {return x + y;}
int main() {
X_plus_Y(); // returns 30
X_plus_Y(20); // set x to 20 so return 40
X_plus_Y(20, 30); // x=20, y=30: return 50
return 0;
}
But I've searched the internet and didn't find any way to pass optional arguments like this:
X_plus_Y(y=30); // to set only the y to 30 and return 40
Is there a way or a "hack" to achieve this result?

Named parameters are not in the language. So X_plus_Y(y=30); doesn't mean anything. The closest you can get is with the following: (works with clang 11 and GCC 10.3)
#include <iostream>
struct Args_f
{
int x = 1;
int y = 2;
};
int f(Args_f args)
{
return args.x + args.y;
}
int main()
{
std::cout << f({ .x = 1}) << '\n'; // prints 3
std::cout << f({ .y = 2}) << '\n'; // prints 3
std::cout << f({ .x = 1, .y = 2 }) << std::endl; // prints 3
}
Check https://pdimov.github.io/blog/2020/09/07/named-parameters-in-c20/ for an in-depth explanation.

Related

How do I make a function that resets a while loop?

I have made a program that outputs 0 3 6 9 12. Now, I want to make a function called reset() that resets the program, so it outputs the same numbers after 12. How do I do that?
#include <iostream>
using namespace std;
void byThrees();
void reset();
int i = 0;
int main()
{
byThrees();
return 0;
}
void byThrees()
{
while(i<13) {
cout << i << ' ';
i += 3;
}
}
void reset()
{
}
Don't use global variables when you can avoid it! And right now, you can avoid it.
No one else wants to use i except byThrees(). And it sounds like you don't want the value of i to persist across runs of byThrees(). So just make it a local variable in the function:
void byThrees()
{
int i = 0;
while(i<13) {
cout << i << ' ';
i += 3;
}
}
Now whenever you want to print your 0, 3, 6, 9, ... series, just call byThrees():
int main() {
byThrees();
std::cout << std::endl; // Add a newline between runs
byThrees();
return 0;
}
Another method to do it, if you want to save memory and just keep one global variable (at least I think this saves memory) is:
#include <iostream>
using namespace std;
int i = 0;
int main()
{
run(); // this function both resets i to 0 and runs byThrees()
return 0;
}
void byThrees()
{
while(i < 13) {
cout << i << ' ';
i += 3;
}
}
void run()
{
i = 0;
byThrees();
}
Basically, whenever you run the function run(), your code will reset the global variable i to 0 and run byThrees() with i being 0 initially. This means that you can repeatedly call run() in your code and every time it will output 0 3 6 9 12.
If what you mean in your post is that you want your code to output 0 3 6 9 12 and then 15 18 21 24 27 on the next call (and so on), you could do something like this:
#include <iostream>
using namespace std;
int i = 0, nextI = 0; // nextI is a variable that stores the next starting position of i
int main()
{
run(); // will output "0 3 6 9 12"
run(); // will output "15 18 21 24 27"
run(); // will output "30 33 36 39 42"
return 0;
}
void byThrees()
{
while(i < nextI + 13) {
cout << i << ' ';
i += 3;
}
nextI += 15; // increases nextI for the next time "run()" is called
}
void run()
{
i = nextI;
byThrees();
}
This code basically keeps track of where the list of numbers left off and continues from there.

Confusion about pointer to an array as a function parameter

In my textbook about c++ I have the following code example:
using std::cout;
using std::endl;
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
cout << "Append: " << endl;
printArray(aArr, 4); cout << " + "; printArray(bArr, 3);
int* cArr = append(&aArr, bArr);
cout << " = "; printArray(cArr, 7); cout << endl;
return 0;
}
Does the "&" symbol in front of "aArr" in the call to append in main mean that the address of aArr is passed, or that a reference to aArr is passed.
The question then asks for me to implement a function append which takes two arrays: the first array (in the first argument) of size 4 by array pointer and the second array (in the second argument) of size 3 by reference and returns a pointer to an array of size 7. I have declared that function as (in the appropriate header file)
int* append( int foo[4], int (&secondArray) [3] );
Has the author perhaps misplaced the order of the "&" symbol in the append method (that it should be in front of "bArr")?
The compiler can help you out in cases like this.
Lets assume that this is the function prototype for your append function:
int* append( int foo[4], int (&secondArray) [3]);
I can test this out with this simple bit of code:
int* append( int foo[4], int (&secondArray) [3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
But the compiler doesn't like this, failing with this error:
test.cpp(9): error C2664: 'int *append(int [],int (&)[3])':
cannot convert argument 1 from 'int (*)[4]' to 'int []'
As you can see it doesn't like the &aArr argument 1 at line 9 as it does not match the argument 1 defined by the function at line 1. From the error message it is even nice enough to give a reason why it thinks they don't line up.
Now using the hint from the compiler it is clear the function should in fact look like this:
int *append(int (*foo)[4], int secondArray[3])
{
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 2,3,1 };
int* cArr = append(&aArr, bArr);
return 0;
}
With that change the compiler is happy to accept the code as correct.
Now comparing the two you can see the difference is in the first case the first argument was passed as an array of 4 integers, whereas in the second case it is passed as the address of an array of four integers.
Just from the english you can tell these are two very different things.
EDIT: Here is an extension of that example that shows how to access the data inside the function.
#include <stdio.h>
int *append(int (*foo)[4], int secondArray[3] )
{
int *foo1 = *foo;
for (int i = 0; i < 4; ++i)
{
printf("foo: %d\n", foo1[i]);
}
for (int j = 0; j < 3; ++j)
{
printf("secondArray: %d\n", secondArray[j]);
}
return 0;
}
int main() {
int aArr[4] = { 3,4,2,3 };
int bArr[3] = { 12,13,11 };
int* cArr = append(&aArr, bArr);
return 0;
}
Compiling an running this code produces this output:
foo: 3
foo: 4
foo: 2
foo: 3
secondArray: 12
secondArray: 13
secondArray: 11

How/Can C++ lambdas retain inner state?

I have a basic lambda that looks like this:
auto l = [](){
int i = 0;
cout << i++;
}
Calling this a bunch of times, will keep printing 0. How can I retain i? Can I do this without functors?
Depending on what you want to do with this lambda, you might consider the following alternative:
auto exec = [i = 0]() mutable { cout << ++i << ' '; };
exec(); // 1
exec(); // 2
auto exec2 = exec; // copy state of lambda
exec2(); // 3
exec(); // 3
Using []() { static int i = 0; cout << ++i << ' '; }; instead will result in the sequence 1 2 3 4 being printed.
Live example
Try to think of a lambda as a class with an operator(). How would you retain state in a class? Have a member. Captures are the equivalent here.
#include <iostream>
auto l = [i=0]()mutable{
std::cout << i++;
};
auto l2=l;
int main(){
l(); // 0
l(); // 1
l(); // 2
l2(); // 0
l2(); // 1
l(); // 3
std::cout << '\n';
}
auto l = [](){
static int i = 0;
// ^^^^^^
cout << i++;
}
should fix your concerns.
In general functions cannot retain inner state without using a local static variable. There's no difference with using lambdas actually.
If you want to count copies, you can use an ordinary functor class implementation as #Revolver_Ocelot suggested.
If you want i to retain its value then you have three options:
Declare i as a global variable (Bad).
Pass previous value of i to the function every time (Better).
Declare i as a static variable (Best).
auto l = []() { static int i = 0; cout << i++ << endl; };
l(); l(); l();
This will give as output:
0
1
2

conditional in value assignment

In c++, I want to use conditionals when assigning values, for example:
int i = true && 5 || 3;
For example, using Lua you can write this:
i = true and 5 or 3
I am not sure that this is possible
Here is something that I tried:
#include "stdafx.h"
#include <iostream>
void main()
{
int test = (true && 5) || 1;
int test2 = (false && 6) || 2;
std::cout << "Test: " << test << std::endl << "Test2: " << test2 << std::endl;
for(;;);
}
C++ isn't Lua.
In Lua, true and 5 expression results in 5. That's simply how Lua works with boolean expressions.
And that's not how C++ works with boolean expressions. In C++, a boolean expression results in a boolean value. That is, either true or false.
If you want to select between two values based on a condition, we have an operator for that:
int i = true ? 5 : 3;
If the condition is true, you get the value before the :. If it's false, you get the value after the :.
I suspect you're looking for int test = true ? 5 : 1;
What you need is a conditional expression:
int i = true ? 2 : 5;
In this case i will be 2.
If we really wanted to, as of c++11 (which gives us the and and or keywords as a synonyms for && and ||), we could almost strong-arm the c++ compiler into compliance, and get it to compile this:
int x = when_true(b) and 5 or 6;
In order to do this we would need to provide some scaffolding:
#include <iostream>
struct maybe_int {
bool cond;
int x;
operator int() const { return x; }
};
int operator || (const maybe_int& l, int r) {
if (l.cond) return l.x;
return r;
}
struct when_true {
when_true(bool condition)
: _cond(condition)
{}
auto operator&&(int x) const {
return maybe_int { _cond, x };
}
bool _cond;
};
int main()
{
using namespace std;
auto b = false;
int x = when_true(b) and 5 or 6;
cout << x << endl;
return 0;
}
My suggestion would be that you don't try this kind of thing at work.

Check if element found in array c++

How can I check if my array has an element I'm looking for?
In Java, I would do something like this:
Foo someObject = new Foo(someParameter);
Foo foo;
//search through Foo[] arr
for(int i = 0; i < arr.length; i++){
if arr[i].equals(someObject)
foo = arr[i];
}
if (foo == null)
System.out.println("Not found!");
else
System.out.println("Found!");
But in C++ I don't think I'm allowed to search if an Object is null so what would be the C++ solution?
In C++ you would use std::find, and check if the resultant pointer points to the end of the range, like this:
Foo array[10];
... // Init the array here
Foo *foo = std::find(std::begin(array), std::end(array), someObject);
// When the element is not found, std::find returns the end of the range
if (foo != std::end(array)) {
cerr << "Found at position " << std::distance(array, foo) << endl;
} else {
cerr << "Not found" << endl;
}
You would just do the same thing, looping through the array to search for the term you want. Of course if it's a sorted array this would be much faster, so something similar to prehaps:
for(int i = 0; i < arraySize; i++){
if(array[i] == itemToFind){
break;
}
}
There are many ways...one is to use the std::find() algorithm, e.g.
#include <algorithm>
int myArray[] = { 3, 2, 1, 0, 1, 2, 3 };
size_t myArraySize = sizeof(myArray) / sizeof(int);
int *end = myArray + myArraySize;
// find the value 0:
int *result = std::find(myArray, end, 0);
if (result != end) {
// found value at "result" pointer location...
}
Here is a simple generic C++11 function contains which works for both arrays and containers:
using namespace std;
template<class C, typename T>
bool contains(C&& c, T e) { return find(begin(c), end(c), e) != end(c); };
Simple usage contains(arr, el) is somewhat similar to in keyword semantics in Python.
Here is a complete demo:
#include <algorithm>
#include <array>
#include <string>
#include <vector>
#include <iostream>
template<typename C, typename T>
bool contains(C&& c, T e) {
return std::find(std::begin(c), std::end(c), e) != std::end(c);
};
template<typename C, typename T>
void check(C&& c, T e) {
std::cout << e << (contains(c,e) ? "" : " not") << " found\n";
}
int main() {
int a[] = { 10, 15, 20 };
std::array<int, 3> b { 10, 10, 10 };
std::vector<int> v { 10, 20, 30 };
std::string s { "Hello, Stack Overflow" };
check(a, 10);
check(b, 15);
check(v, 20);
check(s, 'Z');
return 0;
}
Output:
10 found
15 not found
20 found
Z not found
One wants this to be done tersely.
Nothing makes code more unreadable then spending 10 lines to achieve something elementary.
In C++ (and other languages) we have all and any which help us to achieve terseness in this case. I want to check whether a function parameter is valid, meaning equal to one of a number of values.
Naively and wrongly, I would first write
if (!any_of({ DNS_TYPE_A, DNS_TYPE_MX }, wtype) return false;
a second attempt could be
if (!any_of({ DNS_TYPE_A, DNS_TYPE_MX }, [&wtype](const int elem) { return elem == wtype; })) return false;
Less incorrect, but looses some terseness.
However, this is still not correct because C++ insists in this case (and many others) that I specify both start and end iterators and cannot use the whole container as a default for both. So, in the end:
const vector validvalues{ DNS_TYPE_A, DNS_TYPE_MX };
if (!any_of(validvalues.cbegin(), validvalues.cend(), [&wtype](const int elem) { return elem == wtype; })) return false;
which sort of defeats the terseness, but I don't know a better alternative...
Thank you for not pointing out that in the case of 2 values I could just have just if ( || ). The best approach here (if possible) is to use a case structure with a default where not only the values are checked, but also the appropriate actions are done.
The default case can be used for signalling an invalid value.
You can use old C-style programming to do the job. This will require little knowledge about C++. Good for beginners.
For modern C++ language you usually accomplish this through lambda, function objects, ... or algorithm: find, find_if, any_of, for_each, or the new for (auto& v : container) { } syntax. find class algorithm takes more lines of code. You may also write you own template find function for your particular need.
Here is my sample code
#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
using namespace std;
/**
* This is old C-like style. It is mostly gong from
* modern C++ programming. You can still use this
* since you need to know very little about C++.
* #param storeSize you have to know the size of store
* How many elements are in the array.
* #return the index of the element in the array,
* if not found return -1
*/
int in_array(const int store[], const int storeSize, const int query) {
for (size_t i=0; i<storeSize; ++i) {
if (store[i] == query) {
return i;
}
}
return -1;
}
void testfind() {
int iarr[] = { 3, 6, 8, 33, 77, 63, 7, 11 };
// for beginners, it is good to practice a looping method
int query = 7;
if (in_array(iarr, 8, query) != -1) {
cout << query << " is in the array\n";
}
// using vector or list, ... any container in C++
vector<int> vecint{ 3, 6, 8, 33, 77, 63, 7, 11 };
auto it=find(vecint.begin(), vecint.end(), query);
cout << "using find()\n";
if (it != vecint.end()) {
cout << "found " << query << " in the container\n";
}
else {
cout << "your query: " << query << " is not inside the container\n";
}
using namespace std::placeholders;
// here the query variable is bound to the `equal_to` function
// object (defined in std)
cout << "using any_of\n";
if (any_of(vecint.begin(), vecint.end(), bind(equal_to<int>(), _1, query))) {
cout << "found " << query << " in the container\n";
}
else {
cout << "your query: " << query << " is not inside the container\n";
}
// using lambda, here I am capturing the query variable
// into the lambda function
cout << "using any_of with lambda:\n";
if (any_of(vecint.begin(), vecint.end(),
[query](int val)->bool{ return val==query; })) {
cout << "found " << query << " in the container\n";
}
else {
cout << "your query: " << query << " is not inside the container\n";
}
}
int main(int argc, char* argv[]) {
testfind();
return 0;
}
Say this file is named 'testalgorithm.cpp'
you need to compile it with
g++ -std=c++11 -o testalgorithm testalgorithm.cpp
Hope this will help. Please update or add if I have made any mistake.
If you were originally looking for the answer to this question (int value in sorted (Ascending) int array), then you can use the following code that performs a binary search (fastest result):
static inline bool exists(int ints[], int size, int k) // array, array's size, searched value
{
if (size <= 0) // check that array size is not null or negative
return false;
// sort(ints, ints + size); // uncomment this line if array wasn't previously sorted
return (std::binary_search(ints, ints + size, k));
}
edit: Also works for unsorted int array if uncommenting sort.
You can do it in a beginners style by using control statements and loops..
#include <iostream>
using namespace std;
int main(){
int arr[] = {10,20,30,40,50}, toFind= 10, notFound = -1;
for(int i = 0; i<=sizeof(arr); i++){
if(arr[i] == toFind){
cout<< "Element is found at " <<i <<" index" <<endl;
return 0;
}
}
cout<<notFound<<endl;
}
C++ has NULL as well, often the same as 0 (pointer to address 0x00000000).
Do you use NULL or 0 (zero) for pointers in C++?
So in C++ that null check would be:
if (!foo)
cout << "not found";