I want to make a unit test, basically i have a class Pawn and << return the color of my pawn. The colors of my pawn are retained in a enum.
TEST_METHOD(outputOperator)
{
Pawn pawn(Pawn::Color::Blue);
std::stringstream out;
out << pawn.GetColor();
Assert::IsTrue(Pawn::Color::Blue == out);
}
The problem is that my compiler said that no operator == matches these operands. What can I do ?
PS: This is my second unit test
Related
I feel like this is an easy question but I don't seem to find the answer myself. I was wondering if there is a way of using the enum in another file, without having to use scoping?
e.g. Head.h
namespace h{
class Eye{
enum class State{
closed = 0, blinking, open, staring, rolling // etc.
};
void print(const State &eye);
};
class Body{
Eye::State eye;
Eye::State eyesOpen();
};
}
Head.cpp
namespace h{
void Eye::print(const State &eye){
switch(eye){
case Eye::State::closed: cout << "Closed" << endl;
case Eye::State::blinking: cout << "Blinking" << endl;
case Eye::State::open: cout << "Open" << endl;
}
bool Body::eyesOpen(){
return eye == Eye::open;
}
}
I am using Eye::State about 80+ times in my Body class, so I was wondering if there's a way for me to just state that State is Eye::State rather than having to write it 80 times?
Edit: Eye and Body are two separate classes. It's just that Body uses the Eye object
Don't put a type alias at the top of the namespace unless that's really the logical scope you want.
If you just want to save typing in the Body methods you haven't shown, simply
namespace h{
class Body{
using State = Eye::State;
State eye;
State eyesOpen();
};
}
will work. It seems odd that the eyes are the only organ of this body whose state is important, though. If you really want more organ states later, you can remove the class-level alias and just write
bool Body::eyesOpen() {
using State = Eye::State;
return eye == State::open;
}
(which is no improvement at all, but imagine it's applied to the other 80 instances you haven't shown us).
In Physics logic, I am accustomed to code like this :-
Position+=Velocity;
Velocity+=Acceleration;
//unit of Velocity = unit of Position / time-step
//unit of Acceleration = unit of Position / (time-step^2)
They are all Vector3D - my custom class.
The code works OK.
Then, I revolutionized my library to match standard of popular physic engines, e.g. Bullet.
The time unit is now second (or minutes, etc), not time-step anymore.
Now the valid code becomes:
Position+=Velocity*time_per_timestep;
Velocity+=Acceleration*time_per_timestep;
When the statement is a little complex, it is not easy to realize that the following code that I just added is wrong:
Vector3D velocity=rigidBody->getPosition()-calibrator->getLastPosition();
In some busy/dizzy days, I forgot to add รท time_per_timestep like that.
As a result, my bad day began.
Question:
How to prevent this human error? (with assert?)
My poor solution:
I would create classes Position, Velocity, and Acceleration to enforce it.
For example, Position minus Position will still return Position. I have to enforce that Position cannot implicitly casted to be Velocity.
Disadvantages: Too tedious, reduce maintainability(?), and overkill(?).
Here is a unit tags type:
template<std::ptrdiff_t...Units>
struct unit_tags_t {
template<std::ptrdiff_t...Lhs, std::ptrdiff_t...Rhs>
friend unit_tags_t<(Lhs+Rhs)...>
operator*( unit_tags_t<Lhs...>, unit_tags_t<Rhs...> ) {
return {};
}
template<std::ptrdiff_t...Lhs, std::ptrdiff_t...Rhs>
friend unit_tags_t<(Lhs-Rhs)...>
operator/( unit_tags_t<Lhs...>, unit_tags_t<Rhs...> ) {
return {};
}
friend unit_tags_t operator+( unit_tags_t, unit_tags_t ) { return {}; }
friend unit_tags_t operator-( unit_tags_t, unit_tags_t ) { return {}; }
friend unit_tags_t& operator+=( unit_tags_t& lhs, unit_tags_t ) { return lhs; }
friend unit_tags_t& operator-=( unit_tags_t& lhs, unit_tags_t ) { return lhs; }
friend unit_tags_t operator*( unit_tags_t ) { return {}; }
friend unit_tags_t operator-( unit_tags_t ) { return {}; }
};
it is a compile-time list of signed values.
We pick some base units, like time and distance.
using base_time_t = unit_tags_t<1,0>;
using base_distance_t = unit_tags_t<0,1>;
Now, base_time_t{}+base_distance_t{} is a compile-time error, but base_time_t{}+base_time_t{} is not.
Similarly, base_time_t{}*base_time_t{} is not a compile-time error, but rather a new unit of "time squared".
Next, we define a tuple with augmented operators. It has a scalar as one field, and some unit tag as its second field. All arithmetic operations perform on each of the units in turn, like a mathematical product type.
So if we have
{2.0, base_distance_t}/{3.14, base_time_t}
we get
{0.636..., unit_tags_t<-1,1>{}}
by simply forwarding each operator to each component part.
Call this augmented tuple a "unit value".
The next step is to deal with scalars. Define a global constant of
using time = unit_value<double, base_time_t>;
using distance = unit_value<double, base_distance_t>;
const time second(1./time_per_timestep, {});
const distance meter(1., {});
or whatever is right. We can derive new types:
const auto meter_per_second = meter/second;
const auto meter_per_second_squared = meter/second/second;
using speed = std::decay_t<decltype(meter_per_second)>;
using acceleration = std::decay_t<decltype(meter_per_second_squared)>;
based off these.
Now, getPosition returns a distance value.
velocity is a value of type speed
And
Velocity3D velocity=rigidBody->getPosition()-calibrator->getLastPosition();
is a type error.
If you are using a compressed tuple, the space required for a double or a unit_value<double, blah> should be the same (as should the layout in memory). So you could make Velocity3D to be a unit_value<Vector3d, base_distance_t>, or a Vector3d< base_distance_t >.
A library like boost units will do all this for you; I am simply illustrating how you'd approach it.
C++11 offers you a correct solution to this problem with User-defined literals.
This helps you to prevent incorrect operations between measures by checking them in compile time.
I am currently taking an intermediate c++ class with my university, and we've just done classes/polymorphism and so I decided to work on a little project of my own. This is not homework, figured I'd get that out of the way.
So I'm using SFML to make a little "idle" game. This consists of an entity class, with a class for a weapon and a class for an armor. I have 2 entities, being the player and "other", or the enemy. Everything has been good so far, but I am running into trouble when I am trying to invoke a member function on the entity class with an argument as another entity.
Here are the two functions
/*
Simulates the entity attacking another entity
*/
void Entity::attackEntity(Entity other) {
other.decreaseHP(5);
if (other.getCurrentHP() <= 0) {
killEntity(other);
}
}
/*
Simulates main entity defeating another
*/
void Entity::killEntity(Entity other) {
if (other.getEntityType() == "Enemy") {
other.setXP(rand() % (other.getRequiredXP() / 9) + 1);
addXP(other.getXP());
//addXP(rand() % (rand() % (getRequiredXP() / 10) + 1) + getEntityLevel()); // testing
addGold(rand() % getEntityLevel() + getEntityLevel());
// Increment the level of the entity to give them better armor/weapon
other.incrementLevel();
// Regenerate a weapon and armor for the enemy
other.setWeapon(other.getWeapon().generateRandomWeapon(other.getEntityLevel()));
other.setArmor(other.getArmor().generateRandomArmor(other.getEntityLevel()));
}
else if (other.getEntityType() == "Player") {
other.setXP(other.getXP() / 10);
other.setCurrentHP(other.getMaxHP());
other.refreshEntityInfo();
}
}
Currently, in the main program, I am calling it as
if (clock.getElapsedTime().asSeconds() >= 1.0f) {
player.attackEntity(enemy);
clock.restart();
}
What I want the code to do is every 1 second, the player will "attack" the other entity, being enemy. This will decrease the health points of the other entity by 5, and when the other entity's health points drop below 1, it will "kill" the entity, granting the player experience and resetting the other entity's armor and weapon, which will give it new stats.
However, what is happening, is nothing. Health points do not decrease.
Obviously I am doing something wrong here as it is not working.
I tested just calling the decreaseHP() method alone in the time loop and that works:
if (clock.getElapsedTime().asSeconds() >= 1.0f) {
//player.attackEntity(enemy);
player.decreaseHP(5);
clock.restart();
}
but the way I supplied before using the attackEntity() method does not.
Here is the decreaseHP() method.
/*
Decreases the entity's current health by amount
*/
void Entity::decreaseHP(int amount) {
setCurrentHP(getCurrentHP() - amount);
}
Do I need to pass the other entity object as reference? Am I going about these functions in a poor way? How should I be approaching this?
Edit -- So I know I just posted this, but I changed the parameters for both the attackEntity() function and killEntity() function so it takes the entity object by reference, and that seemed to solve the solution.
/*
Simulates main entity defeating another
*/
void Entity::killEntity(Entity &other) {
if (other.getEntityType() == "Enemy") {
other.setXP(rand() % (other.getRequiredXP() / 9) + 1);
addXP(other.getXP());
//addXP(rand() % (rand() % (getRequiredXP() / 10) + 1) + getEntityLevel()); // testing
addGold(rand() % getEntityLevel() + getEntityLevel());
// Increment the level of the entity to give them better armor/weapon
other.incrementLevel();
// Regenerate a weapon and armor for the enemy
other.setWeapon(other.getWeapon().generateRandomWeapon(other.getEntityLevel()));
other.setArmor(other.getArmor().generateRandomArmor(other.getEntityLevel()));
}
else if (other.getEntityType() == "Player") {
other.setXP(other.getXP() / 10);
other.setCurrentHP(other.getMaxHP());
other.refreshEntityInfo();
}
}
/*
Simulates the entity attacking another entity
*/
void Entity::attackEntity(Entity &other) {
other.decreaseHP(5);
if (other.getCurrentHP() <= 0) {
killEntity(other);
}
}
However, my last questions still stand: am I going about this the right way?
The signature void Entity::attackEntity(Entity other) causes other to be a copy of the entity. Any changes made to other are local to the attackEntity function.
If you need the changes to persist from the source item, the most straight forward way is to pass other in by reference, changing the signature to: void Entity::attackEntity(Entity& other)
Given this...
void Entity::attackEntity(Entity other) {
... then this code
Entity x;
foo.attackEntity(x);
... will create a COPY of X, pass that to attackEntity, which modifies the local copy that's immediately discarded. So x stays unchanged.
In this case, use pass by reference.
void Entity::attackEntity(Entity &other)
If the method isn't meant to modify x, use pass by const reference instead:
bool Entity::isWithinRange(const Entitiy &other)
Following from your edit, yes, references are absolutely the correct way of handling this. Passing objects by value (or as pointers) is often a code 'smell'.
Check your use of the equality operator, "==". C++ doesn't treat strings the way Java and C# do. Quoted strings (e.g. "Enemy") decompose into pointers, so the comparison becomes "does this pointer point to the same address as the other pointer does," the answer to which will pretty much always be "no."
You can try using the std::string type, which defines a compare() method, but in general, C++ strings are only slightly friendlier than C strings.
You should probably be using the old-fashioned C string comparison functions such as strcmp().
I have created a class that allows the user to input their mailing address, order date, type of cookie ordered and the quantity. There were other errors, but I stayed late and with the assistance of my prof, I have fixed them. Now all that is left is that I need to be able to change code to overload the I/O stream operators so that the objects may be used in standard input and output statements.
I'm not sure what all part of the code everyone will need to see, but I'm going to post the parts I believe are needed for what I'm trying to do.
I need to have it where in the output(), I have cout << order << endl; I will look over the net and will hopefully have it ready by tonight. Thanks for everyone's input.
Was instructed to take down my code due to other students from class copying my code pieces to do their work (knew it was possible but didn't think about it)
However, my code is complete.
Implement two functions:
basic_ostream & operator<< (basic_ostream& ostr, const CookieOrder& co)
basic_istream & operator>> (basic_istream& istr, CookieOrder& co)
the operator<<= function will be called when you use cout << order << endl; and the operator>> function will be called when you use the >> (stream extraction) operator. Be very careful how you implement the stream extraction operator.
You may want to declare either of these as friend to the CookieOrder, as that will allow the function to access the private parts of the class as if the function is a member of the class.
edit to respond to changes in the question
delcare your class as before:
class CookieOrder {
public:
// public methods as before
private:
// private parts as before
};
basic_ostream & operator<< (basic_ostream& ostr, const CookieOrder& co);
basic_istream & operator>> (basic_istream& istr, CookieOrder& co);
Implement the two functions using only the public interface of the CookieOrder class.
For example:
basic_ostream & operator<< (basic_ostream& ostr, const CookieOrder& co)
{
ostr << co.get_customerName() << endl;
/* the rest of the output */
}
These functions are not members of the CookieOrder class, they are normal functions with no special access to the CookieOrder class or instanaces of the class.
As far as comparison is concerned, you'd be better off comparing all upper or all lower (rather than each word's first letter upper), it's simpler to set things that way.
Moreover you should get into the habit of putting braces around code
Why do you have a magic number of 6 in your loop? Especially when you only have five (5) elements.
Perhaps the loop should be
...
int loop_size = sizeof(flavors)/sizeof(flavors[0]);
for (int i = 0; i < loop_size; ++i)
{
if (flavors[i] == cookieOrdered)
{
valid_option = true;
break;
}
}
Hint: lookup Case insensitive string comparison in C++
I have run into trouble trying to implement functionality for serializing some classes in my game. I store some data in a raw text file and I want to be able to save and load to/from it.
The details of this, however, are irrelevant. The problem is that I am trying to make each object that is interesting for the save file to be able to serialize itself. For this I have defined an interface ISerializable, with purely virtual declarations of operator<< and operator>>.
The class Hierarchy looks something like this
-> GameObject -> Character -> Player ...
ISerializable -> Item -> Container ...
-> Room ...
This means there are many possible situations for serializing the objects of the different classes. Containers, for instance, should call operator<< on all contained items.
Now, since operator>> is virtual, i figured if I wanted to serialize something that implements the functionality defined in ISerializable i could just do something like
ostream & Player::operator<<(ostream & os){
Character::operator<<(os);
os << player_specific_property 1 << " "
<< player_specific_property 2 << "...";
return os;
}
and then
ostream & Character::operator<<(ostream & os){
GameObject::operator<<(os);
os << character_specific_property 1 << " "
<< character_specific_property 2 << "...";
return os;
}
but I quickly learnt that this first attempt was illegal. What I'm asking here is how do I work around this?
I don't feel like implementing a function manually for each class. I guess I'm looking for something like the super functionality from Java.
Any help is appreciated.
-- COMMENTS ON EDIT ------------
Alright, last time I was in a hurry when I was writing the question. The code is now more like it was when I tried to compile it. I fixed the question and the problem I had was unrelated to the question asked. I'm ashamed to say it was caused by an error in the wake of a large refactoring of the code, and the fact that the operator was not implemented in every base class.
Many thanks for the replies however!
The problem is not in your attempt to call a virtual function non-virtually. The problem is this line: os = Character::operator<<(os);. That is an assignment, but std::ostream doesn't have an operator=.
You don't need the assignment anyway. The stream returned is the same stream as the stream you pass in. The only reason it's returned is so you can chain them.
Hence the fix is to just change the code to
ostream & Player::operator<<(ostream & os){
Character::operator<<(os);
os << player_specific_property 1 << " "
<< player_specific_property 2 << "...";
return os;
}
This is not how overloading operator<< for ostream works. The left-hand operator is an ostream (hence you gotta overload it as a free function) and the right-hand operator is your object (which is why the virtual mechanism wouldn't easily work.
I suppose you could try:
class Base
{
//...
virtual std::ostream& output(std::ostream&) const;
};
std::ostream& operator<< (std::ostream& os, const Base& obj)
{
return obj.output(os);
}
Now a derived class naturally might call the output method of its parent(s):
class Derived: public Base
//...
virtual std::ostream& output(std::ostream& os) const
{
Base::output(os);
return os << my_specific_data;
}
};