all_of asking for argument list - c++

After using all_of succesfully once I tried to do it again.
if (all_of(Enemies.begin(), Enemies.end(), in_lock_range))
{
lock_on = -1;
}
The vector is:
std::vector<Enemy> Enemies;
The function is:
bool Player::in_lock_range(Enemy arg)
{
if (get_distance(mouseTarget.x, mouseTarget.y, arg.x, arg.y) > arg.erect.r) return true;
else return false;
}
get_distance(x1,x2,y1,y2) returns the distance from 2 points
Enemy is a friend class to Player and vice versa so they use each other's stuff freely.
The error I recieve is
error C3867: 'Player::in_lock_range': function call missing argument list; use '&Player::in_lock_range' to create a pointer to member
I'm not sure why he is apparently asing for agruments for in_lock_range when I don't believe it needs any when in all_of, as I have used it in a different situation with no such issue.
Can anyone please explain to me what the cause of this can be? I am not really experienced in this. Thanks.

It's a member function, so the syntax for taking a pointer is
&Player::in_lock_range
This is only usable if it's a static member, since it must be callable with just a single argument. I'm guessing it isn't - presumably mouseTarget is a non-static data member of Player. In that case, you'll have to bind it to some player object:
bind(&Player::in_lock_range, std::ref(some_player), std::placeholders::_1)
or wrap it in a lambda:
[&](const Enemy& e){return some_player.in_lock_range(e);}
The function should probably take its argument by constant reference rather than value; and you might want to simplify the return statements
if (whatever) return true;
else return false;
to the more readable
return whatever;

Related

How can I retrieve a specific member from a class with a getter inside of a function that uses an iterator inside of a loop?

I'm trying to make a function that returns a class (CTaxGroup) by taking as parameter a TaxGroupId.
The function will loop through a vector with an iterator.
int m_TaxGroupId;
CTaxGroup CTaxGroupVector::FetchTaxGroup(int TaxGroupId)
{
CTaxGroup l_TaxGroup;
std::vector<CTaxGroup>::iterator l_iterator =m_TaxGroupVector.begin();
for(l_iterator; l_iterator != m_TaxGroupVector.end(); l_iterator++)
{
int l_TaxGroupId = *l_iterator->GetTaxGroupId();
if(l_TaxGroupId == TaxGroupId)
{
l_TaxGroup = *l_iterator;
}
}
return l_TaxGroup;
}
std::vector<CTaxGroup> CTaxGroupVector::GetTaxGroupVector()
{
return m_TaxGroupVector;
}
At line 7, I get an error from my IDE (RAD Studio XE4) which states :
"E2062 Invalid indirection".
I know that it was something to do with the pointer, but I'm not sure what is my error.
I'm expecting that line 7 would return me an integer.
Without testing, since you don't provide a compilable program, it's likely that you should put parentheses around the initial dereferencing, (*l_iterator)->GetTaxGroupId(), so that the compiler knows you're trying to access a member of a CTaxGroup, not a member of an iterator.

Access member of returned struct in boost lambda/phoenix

I want to replace some older code with simpler, functor based code. But I don't want to introduce a functor class for this and use boost::lambda/phoenix for this as I don't have C++11 at hand.
Old code looks like this
int player = ...;
Point middlePt = ...;
for(Point pt=<magic with nested loops>)
if(this->IsMilitaryBuilding(pt) && (this->GetNode(pt).owner == player + 1))
return true;
return false;
I have a function that calls Functor for every point (encapsulating the magic) and returns true when any of those calls returns true:
template<class Functor>
bool CheckPts(Point middlePt, Functor f);
Translating this for the first part of the if is easy:
return CheckPts(middlePt, bind(&IsMilitaryBuilding, this, _1));
And for the 2nd I'd want to do something like: bind(&GetNode, this, _1).owner == player+1 which is not supported.
What is the most readable way of doing this? I think this might be solvable by binding a reference to this and calling the functions directly using phoenix lambda but I did not found any references that go beyond simple 'Hello World' lambdas accessing only a simple member or a parameter.

C++ Store Function without Argument

Say that you define a callback function as such:
typedef std::function<void(float)> Callback;
And you have a function as such:
void ImAFunction(float a)
{
//Do something with a
}
Is there a way to be able to store a function without an argument then pass one to it at a later time?
Such as this:
//Define the Callback storage
Callback storage;
storage = std::bind(ImAFunction, this);
//Do some things
storage(5);
This wont work which I explain with some of my real code below.
I can get close to what I wan't if I bind the value in with the std::bind function. Such as:
//Change
//storage = std::bind(ImAFunction, this);
storage = std::bind(ImAFunction, this, 5.0); //5.0 is a float passed
This works but when I go to pass a value through the function the outcome is whatever I set it to before:
storage(100); //Output is still 5
I am basing the fact that I think this is possible on this article.
http://www.cprogramming.com/tutorial/function-pointers.html
It doesn't use the function or bind functions but it does pass pointer arguments and performs exactly what I need. The reason I don't just skip the bind function is because I am trying to store the function in a class (private) and I can't store it if it's a template because it's created with the class.
The error produced above comes from this code:
struct BindInfo {
Callback keyCallback;
int bindType;
bool isDown;
bool held;
std::string name;
};
template <class T1>
void bindEvent(int bindType, T1* keydownObj, void(T1::*keydownF)(float), std::string name)
{
BindInfo newKeyInfo = { std::bind(keydownF, keydownObj), bindType, false, false, name };
inputBindings.insert(std::pair<int, BindInfo>(BIND_NULL, newKeyInfo));
};
The error is:
No viable conversion from '__bind<void(Main::*&)(float), Main *&>' to 'Callback' (aka 'function<void (float)>'
Is this possible? Thanks in advance.
You can include a placeholder for an unbound argument:
std::bind(&Main::ImAFunction, this, std::placeholders::_1);
If you find that a bit of a mouthful, a lambda might be more readable:
[this](float a){ImAFunction(a);}
It sounds like what you're looking for is a function pointer. While I don't have a lot of experience using them in C++ I have used them in C so: Yes, it is possible. Perhaps something like this:
void (*IAmAFunctionPointer)(float) = &IAmAFunction;
The best way to think about that line is, that IAmAFunctionPointer is a pointer (hence the *), it returns a void, and takes a float. Then later:
float a = 5;
IAmAFunctionPointer(a);
You could even design it so that the callback function is passed into the method (I assume this is what you're looking for).
void DoStuffThenCallback(float a, void (*callback)(float))
{
//DoStuff
callback(a);
}
further reading: http://www.cprogramming.com/tutorial/function-pointers.html

Using std transform on a C++ string

I am trying to get a bit of practice with std::transform by using it to decrypt a simple Caesar cypher. But apparentrly my function definition is wrong, since the compiler considers the unary function argument invalid. Here is my code:
char CryptoModule::UndoCaesar(char& letter)
{
return (letter - atoi(key_.c_str()) % 128);
}
void CryptoModule::DecryptCaesar()
{
std::transform(data_.begin(), data_.end(), data_.begin(), UndoCaesar);
}
Could anyone please tell me where the error lies ? In addition, what would I need to modify in order to use for_each ? I believe it would involve changing the return value to a void and storing the result in letter.
Thanks and have a nice day
Edit: Tried adding bind, but still not working. Current call is :
std::transform(data_.begin(), data_.end(), data_.begin(), bind(&UndoCaesar, this, std::placeholders::_1));
Your given member function has a hidden this parameter, so you need to bind that in order to pass it:
std::transform(data_.begin(), data_.end(), data_.begin(),
std::bind(&CryptoModule::UndoCaesar, this, std::placeholders::_1)
);
Note that std::bind is in <functional>. All this does is basically cause std::transform to call whatever function-like object, f, it takes like f(currentElement) and have that in turn call UndoCaesar(this, currentElement) with this being part of its state because you bound it.
Alternatively, you can wrap the call in a lambda that captures this so that it can be used for the member function call (implicitly, like normal):
std::transform(data_.begin(), data_.end(), data_.begin(),
[this](char c) {return UndoCaesar(c);}
);

Downcasting a base class in a container to a derived class

I'll show my code first then explain my issue:
std::vector<std::unique_ptr<SGUIObject> > m_objects;
const std::unique_ptr<SGUIObject>& SGUIManager::getObject(const std::string& object_name)
{
for (auto const& iter : m_objects)
{
if (iter.get()->getObjectName() == object_name)
return iter;
}
}
//SButton is derived from SGUIObject
//m_clicked is a boolean member in SButton (private)
//isClicked is a public member method of SButton
const bool isClicked() const { return m_clicked; }
if (dynamic_cast<SButton>(SSceneManager::getGUIManager().getObject("testbutton").isClicked()))
std::cout << "Clicked!" << std::endl;
I just copy pasted from several different files, so it looks weird when all put together. Anyways, what I'm trying to do is downcast from a SGUIObject to a SButton and call isClicked() in an if/else loop. When I do my current code, Code::Blocks gives me this error:
error: 'const class std::unique_ptr' has no member named 'isClicked'|
I have a feeling I'm having a slight syntactical issue, and I'd be extremely grateful if someone was to explain it to me.
Thanks!
I think you mean:
dynamic_cast<SButton*>(SSceneManager::getGUIManager().getObject("testbutton").get())->isClicked()
You want to call isClicked on the result of the dynamic_cast, not the result of getObject.
This line has several problems:
if (dynamic_cast<SButton*>(SSceneManager::getGUIManager().getObject("testbutton").isClicked()))
First SSceneManager::getGUIManager().getObject("testbutton") return a unique_ptr reference. And as the compiler said, unique_ptr does not hae an isclicked method. For that, you would need to use the -> operator which is overloaded to return the underlying pointer.
Second, even if it worked, you can not dynamic_cast a bool to a pointer.
You could do something like
if (dynamic_cast<SButton*>(SSceneManager::getGUIManager().getObject("testbutton").get())->isClicked) ...
Although you might want to separate it in 2 lines to make sure dynamic_cast does not give you a NULL pointer.
SBButton* button = dynamic_cast<SButton*>(SSceneManager::getGUIManager().getObject("testbutton").get());
if (button && button->isClicked()) ...