Passing a bool as a param. C++ - c++

what I am trying to do is an example below.
let's first define a bool.
bool cat = {false};
lets make a fake bool here.
bool setcat(bool booltoset)
{
booltoset = true;
return booltoset;
}
now lets call it with cat.
printf("cat is %s", cat?"true":"false"); //set cat as false.
my question is; is it possible to actually pass a bool through an argument than set that bool?

You need to pass by reference, i.e.:
void setcat(bool& booltoset)
{
booltoset = true;
}

Any function argument is just a variable with scope identical to the function body. If it's an ordinary automatic variable, then changing it has not effect on the caller. This is sometimes useful: you can actually use the arguments, for example:
template<typename F>
void for_each(noexcept_it i, const noexcept_it end, const F &f) noexcept(noexcept(f))
{
for(; i!=end; ++i) f(i); // use i as iteration variable.
}
though the compiler will optimise such things anyway in most cases.

Related

Is it possible to return a reference via an argument passed by reference?

I want to return a boolean or success/failure enum from the function and modify an argument by reference. However, I want to construct a reference in the calling function instead of copying the value.
I have some container (say 'example_q' of type std::queue). queue.front() will return a reference to the value stored in the queue. I can make a copy of that reference (example A) or I can take a reference of that reference (example B), allowing the value to stay in the queue but be utilized outside of it.
A)
int a = example_q.front();
B)
int& b = example_q.front();
Using this difference I could also return the queued value:
A)
int get_front()
{
int a = example_q.front();
return a;
}
B)
int& get_front()
{
return example_q.front();
}
Using option 'B' I can avoid unnecessary copies without moving the data out of the queue via std::move() semantics.
My question is, can I do 'B' via an argument passed by reference? Would I need to use std::move()/rvalues/&& somehow?
void get_front(int& int_ref)
{
// somehow don't copy the value into referenced int_ref, but construct
// a reference in the caller based on an input argument?
int_ref = example_q.front();
}
The problem this would solve is making API match other functions that modify reference arguments but return a success/failure value, ie:
if(q.get_front(referrence_magic_here))
{
...
}
I could reverse the order to get the desired result, IE:
int& get_front(bool& success)
{
...
}
But I'd rather keep the pattern of my API as well as being able to do it via a single line in the if() statement if possible.
Perhaps something like:
bool get_front(int&& int_rvalue)
{
...
int_rvalue = example_q.front();
...
return true_or_false;
}
void calling_func()
{
...
if(get_front(int& magical_ref))
{
... //use magical_ref here?
}
...
}
No, you can't do that.
Other than in its initialiser, a reference behaves like the thing it refers to. By passing it as a function argument, you "hide" the initialiser from the part that wants to do the assignment. So, the function has no access to the referencey behaviour of the thing.
You will have to use pointers if you want to do that:
void get_front(int*& int_ptr)
{
int_ptr = &example_q.front();
}
int* ptr = nullptr;
get_front(ptr);
// optional:
int& ref = *ptr;
(Ew!)
Option B was fine.
This code is invalid C++:
if(get_front(int& magical_ref))
You cannot declare a new variable as you're passing it to a function. And because a reference variable must be declared and initialized at the same time, it wouldn't be possible to have a reference be initialized by passing it to a function.
You could however, do this:
if(int &magical_ref = get_front()) {
But note that you'd be checking whether magical_ref is 0 or not, which is different from the condition you have in your example.
If your logic is as simple as comparing the int, you could do:
if (int& magical_ref = get_front(); magical_ref == 42)
You can return a std::tuple<int&, /* status condition */> and check the status. For example:
std::tuple<int&, bool> get_front() {
static int example = 0;
return {example, false};
}
...
// C++17's structured bindings + if statement with initializer
if (auto [ref, success] = get_front(); success) {
ref = 42;
}
Demo

remove_if: Predicate error when passing a function returning bool

I have this pre-defined function.
void attack(std::vector<GameObject*> objects, unsigned damage) {
for (GameObject* object : objects) {
object->takeDamage(damage);
auto isDead = object->isDead();
objects.erase(std::remove_if(objects.begin(),objects.end(),isDead), objects.end());
}
}
This is my isDead function
bool isDead() const {
if (destructed) {
std::cout << "memory error" << std::endl;
}
return life <= 0;
}
This is the error I keep getting. Have tried a lot of things, but not at all able to figure this one out. Any help appreciated!
error: expression cannot be used as a function
{ return bool(_M_pred(*__it)); }
isDead is a variable in the function. You can't use it as an argument to remove_if.
You can't use a regular member function as argument to std::remove_if either. Use a lambda function instead.
Don't erase objects from a container while you are iterating over it using a range for loop.
Change the argument to attack to be a reference. Otherwise, you will be removing objects from a copy, not the original container.
Here's an updated version of attack:
void attack(std::vector<GameObject*>& objects, unsigned damage)
{
for (GameObject* object : objects)
{
object->takeDamage(damage);
}
objects.erase(std::remove_if(objects.begin(),objects.end(), [](GameObject* object){return object->isDead();}), objects.end());
}
isDead() is a member function of one of your classes, which is exactly why it doesn't work: you did not supply this pointer (object instance) for it to be called on. Oh, and the predicate for remove_if must have exactly one argument of the type objects::value_type.
Do this instead:
objects.erase(std::remove_if(objects.begin(),objects.end(),[](GameObject* object){return object->isDead()), objects.end());

C++ List sort function

I don't know how to correctly implement the a sort for a list in C++. I am getting the build errors:
'Ranker::compare': function call missing argument list; use '&Ranker::compare' to create a pointer to member
How do I correctly implement my sort function for the list?
Ranker.h:
list<Competitor*> sorted;
Ranker.cpp:
bool Ranker::compare(Competitor* first, Competitor* second) {
if (first->getTime() < second->getTime())
return true;
else
return false;
}
int Ranker::addList(Competitor* starter) {
sorted.push_back(starter);
sorted.sort(compare);
}
Just make rankor a simple functor:
struct Compare
{
bool operator()(Competitor* first, Competitor* second) const {
return first->getTime() < second->getTime();
}
};
// STUFF
sorted.sort(Compare());
Or if you have C++11
sorted.sort([](Competitor* first, Competitor* second) {
return first->getTime() < second->getTime();
});
Ranker::compare() is a member function. Member functions are tied to instances. Try using either a static method or a "free" function.
The function Ranker::compare() actually has three arguments: In addition to the two Competitor objects, it also takes an implicit pointer to the object as parameter. However, the binary predicate passed do std::list<...>::sort() only takes two parameters.
The easiest fix is probably to make the function a static member. Not, however, that this is probably not the fastest approach because function pointers can rarely be inlined. If you want to reduce the function call overhead, you might want to encapsulate the logic into a a suitable function object:
struct RankerCompare {
bool operator()(Competitor const* first, Competitor const* second) const {
return first->getTime() < second->getTime();
}
};
...
sorted.sort(RankerCompare());
BTW, a Boolean doesn't become more Boolean by returning true or false from a conditional statement! It is perfectly OK to return a Boolean value directly!

Can I use std::set<std::string> as a default parameter for a function?

I'm new to this and now sure whether this is doable. I want to add a argument of std::set<std::string> to a function, and set its default value to be NULL, to avoid impact on previous uses.
So basically,
func(int a); turns into
func(int a, std::set<std::string> & temp = NULL);
but this will give me an error "error C2440: 'default argument' : cannot convert from 'int' to 'std::set<_Kty> &'"
Can anybody help me on this?
Thanks
In order to set the default to NULL, you'd have to be passing an std::set<std::string>*, not a reference to a value type.
Furthermore, if you are passing a non-pointer type and you want to assign any default value at all, it has to be a const reference, because you can't (advisably!) assign a temporary to it otherwise.
So your choices for "default" values are basically:
std::set<std::string>* = NULL
or:
const std::set<std::string>& = std::set<std::string>()
or option 3, using function overloading more directly:
void myfunction() {dothing(0);}
void myfunction(std::set<std::string>& optional_param)
{ dothing(optional_param.size()); }
or option 4, having a corresponding bool indicating whether parameter is "set":
void myfunction(std::set<std::string>& param, bool param_has_meaning=true) {}
It looks like you're already on the track to the third option. You just need to write two definitions, one with and one without the parameter.
You have the right idea - using a reference. However, a reference cannot be NULL by default, like a pointer can. Therefore, what you probably want to do is overload the function so that you use void func(int a) when you don't want to pass a set as a parameter and use void func( int a, std::set<std::string>& temp)
This way, you can actually provide two separate implementations - one that works on a set and one that doesn't. From a usage point of view, it would have the same effect as a default parameter. From a coding point of view, each implementation would have a clearer purpose.
If you're not going to be modifying the set, might I suggest using a const reference instead:
void func( int a, const std::set<std::string>& temp )
You can't have a NULL reference in C++.
The simplest way would be to have a dummy empty set:
std::set<std::string> empty;
void func(int a, std::set<std::string>& temp = empty)
{
// ...
}
You can then call:
func(1);
Neater, still, would be to use function overloading to create a wrapper so that you have no need to default:
void func(int a, std::set<std::string>& temp)
{
}
void func(int a)
{
std::set<std::string> empty;
func(a, empty);
}
// And then...
func(1);
All this assumes that if you pass in a set you're going to modify it somehow. It's not clear from your question what your intention is but I've made the assumption on the basis that your reference is non-const. If I've miscalculated, then the answer is even simpler:
void func(int a, const std::set<std::string>& temp = std::set<std::string>())
{
}
The following will give you an empty set object:
std::set<std::string>()

C++ parameter is a pointer to a constant object but the updated object is not returned?

I have native C++ class SrcClass containing the following:
std::vector<shotEntry> objectsQueue;
bool getRelatedEntry(const entryToProcess *entriesDeets, int &i) const {
if (i >= (int)objectsQueue.size()) {
i = 0;
return false;}
if (!objectsQueue.size()) return false;
entriesDeets = &(objectsQueue[i++]);
return true;
}
In my client I have:
const entryToProcess *entriesDeets = NULL;
int i = 0;
while (srcObj->getRelatedEntry(entriesDeets, i)) {
When I step through getRelatedEntry the formal parameter, entriesDeets is updated as expected before returning. When it returns the actual parameter of the client is not updated.
This is in some big project I have returned to after two months away. I'm pretty sure the last refactoring I did was to introduce these damnable vectors. It takes ages to compile when I mess with headers. Am I getting confused with the initialize once/ readonly/ const'ness of C#? Can I get away with the client getting a read only native object back?
This is because you are setting the value of the function's parameter. You want:
bool getRelatedEntry(const entryToProcess **entriesDeets, int &i) const {
...
*entriesDeets = &(objectsQueue[i++]);
...
and
srcObj->getRelatedEntry(&entriesDeets, i)
entriesDeets is a local variable inside getRelatedEntry. You only modified the local, you didn't affect the value passed in. You need to pass a reference to pointer or a pointer to pointer.
The pointer is updated, but it is the internal copy inside the function. If you want that change to be visible outside of the function, you should pass a reference:
// v
bool getRelatedEntry(const entryToProcess *&entriesDeets, int &i) const {
Or in C style a double pointer and dereference it internally on every usage:
// v
bool getRelatedEntry(const entryToProcess **entriesDeets, int &i) const {
// ...
*entriesDeets = &(objectsQueue[i++]);