The issues when avoiding object slicing using CRTP - templates

I'd like to avoid object slicing by using dynamic_cast. I'm trying to use CRTP to avoid writing assignment operator for every derived class. The base class is "Shape" and there are several derived classes("Circle" is an example). The purpose is to just use other Shape class as a template without writing assignment operator for each of them, like this class squre: public ShapeCopyable<square> However, the compiler complains at the line of return *this; saying:
error C2440: 'return': cannot convert from 'ShapeCopyable' to 'Circle &'
But it looks ok to me because the inheritance is this: Shape->ShapeCopable->Circle. I should be able to return an object of ShapeCopyable to a reference of Circle because they are from the same inheritance hierarchy, right? Where's the error? How should I fix it?
BTW, the vector of Shape* is the holder of all kinds of Shape pointers and the pointers held by it will be distributed to their corresponding Shape(square, circle, etc) vectors later on.
The code is enclosed below.
class Shape {
protected:
string name;
int edges;
virtual void assign(const Shape &rhs) {
name = rhs.name;
edges = rhs.edges;
}
};
template<typename T>
class ShapeCopyable : public Shape
{
public:
T & operator=(const Shape& s)
{
T const& c = dynamic_cast<T const&>(s); // Throws on bad cast.
assign(c);
return *this; //The compiler complains at this line
}
};
class Circle: public ShapeCopyable<Circle> {
private:
int radius;
public:
// preferably, this operator= is not needed.
Circle & operator=(Shape const &rhs) {
ShapeCopyable<Circle>::operator=(rhs);
return *this;
}
Circle(int in = 0) :radius(in) {}
std::string getName() { return name; }
int getEdges() { return edges; }
int getRadius() { return radius; }
void setRadius(int r) { radius = r; }
protected:
void assign(const Circle & rhs) {
Shape::assign(rhs);
radius = rhs.radius;
}
};
main()
{
std::vector<Shape*> shapes;
std::vector<Circle*> circs;
Circle c2(5); //Creates a circle with 5 for the radius.
shapes.push_back(&c2); //Pushing the 5-radius circle into the Shapes* vector
Circle c3; //Creates a circle with default constructor (which does NOT define radius)
c3 = *shapes[0]; //Now, the overloaded assignment operator. Look at Circle::assign(const Shape&) function
circs.push_back(&c3); //We push our newly assigned circle to our Circle vector
std::cout << "c3 radius: " << circs[0]->getRadius(); //This will be 5!
}

Change the line:
return *this; //The compiler complains at this line
to this:
return dynamic_cast<T&>(*this);
The reason why the compiler complained about it is because you are trying to return a ShapeCopyable when the compiler is expecting a reference to a concrete shape like Circle or Square.
There is no implicit conversion from a reference to a base class to a reference to a derived class, which necessitates a cast.

Ok, I'm answering my own question... After the following fix, the code worked as I expected.
template<typename T>
class ShapeCopyable : public Shape
{
public:
T & operator=(const Shape& s)
{
T const& c = dynamic_cast<T const&>(s); // Throws on bad cast.
static_cast<T*>(this)->assign(c); //this line got fixed
return dynamic_cast<T&>(*this); //this line got fixed
}
};
class Circle: public ShapeCopyable<Circle> {
private:
int radius;
public:
using Shapecopyable<Circle>::operator=; //this line got fixed
Circle(int in = 0) :radius(in) {}
std::string getName() { return name; }
int getEdges() { return edges; }
int getRadius() { return radius; }
void setRadius(int r) { radius = r; }
//The rest code is the same as before
...
...
}

Related

How can I make a function use the child object associated function instead of the parent one?

I'm coding a simple physics engine with a few others for a school assignment. In order to be as generic, we made a Particle class, then an Object class which inherits it (and is basically a particle with a force vector), and finally a Disc class which is a child class of Object.
In my class PyhsicsWorld, I want to use a list of Objects and iterate on it to resolve collisions. For that, I declared the intersects(Object o1, Object o2) and GetPenDist(Object o1, Object o2) functions, but they aren't supposed to be called. Instead, I'm overloading these functions in Disc and I want the program to use these instead.
I only create and use Discs (for now), so I'm sure there isn't any reason (other than me not understanding my code) for the program to call intersects on Objects instead of Disc. Here is my code :
Object.h :
#include <iostream>
#include "./Particle.h"
class Object : public Particle {
//Some code
};
bool intersects(Object o1, Object o2);
float getPenDist(Object o1, Object o2);
Object.cpp :
#include "./Object.h"
bool intersects(Object o1, Object o2) {
std::cout << "Bad Intersects" << std::endl;
return false;
}
float getPenDist(Object o1, Object o2) {
std::cout << "Bad PenDist" << std::endl;
return 0;
}
Disc.h :
#include "./Object.h"
class Disc : public Object {
protected :
float radius;
public :
float getRadius() { return radius; }
//Some code
};
bool intersects(Disc d1, Disc d2);
float getPenDist(Disc d1, Disc d2);
Disc.cpp :
#include "./Disc.h"
bool intersects(Disc d1, Disc d2) {
return (d2.getPosition() - d1.getPosition()).getNorm() < d1.getRadius() + d2.getRadius();
}
float getPenDist(Disc d1, Disc d2) {
return -(d2.getPosition() - d1.getPosition()).getNorm() - d1.getRadius() - d2.getRadius();
}
PhysicsWorld.h :
class PhysicsWorld {
protected:
std::vector<Object*> objectList;
void resolveCollisions(float duration);
};
PhysicsWorld.cpp :
#include "PhysicsWorld.h"
void PhysicsWorld::resolveCollisions(float duration) {
std::vector<Object*>::iterator iter, iter2;
for (iter = objectList.begin(); iter != objectList.end(); ++iter) {
for (iter2 = objectList.begin(); iter2 != objectList.end(); ++iter2) {
if (!(*iter == *iter2))
{
if (intersects(**iter, **iter2))
{
//Do something
}
}
}
}
}
My problem here is that the code is running the Intersects(Object*, Object*) function in the resolveCollisions method while I'd like it to run the Intersects(Disc*, Disc*) function.
Please note that these classes are heavily simplified to only include relevant code.
Furthermore, while I'd love to make Object::Intersects(Object o), I can't do that as I can't override it afterward with Disc::Intersects(Disc d).
Thank you very much for any help you can provide !
If you really need to call for Disc, just cast it. I further assume that you need general solution for multiple shapes, like Disc, Cube, Sphere etc.
So I prepared example for you, that is based on virtual functions and shows how can you choose correct function for Disc and Cube.
class Disc;
class Cube;
bool intersectDiscVsDisc(Disc*, Disc*);
bool intersectCubeVsDisc(Cube*, Disc*);
bool intersectCubeVsCube(Cube*, Cube*);
class Object {
public:
virtual bool intersects(Object *) = 0;
virtual bool intersectsVsDisk(Disc *) = 0;
virtual bool intersectsVsCube(Cube *) = 0;
};
class Disc : public Object {
virtual bool intersects(Object * another) override
{ return another->intersectsVsDisk(this); }
virtual bool intersectsVsDisk(Disc * another)
{ return intersectDiscVsDisc(this, another); }
virtual bool intersectsVsCube(Cube * another)
{ return intersectCubeVsDisc(another, this); }
};
class Cube : public Object {
virtual bool intersects(Object * another) override
{ return another->intersectsVsCube(this); }
virtual bool intersectsVsDisk(Disc *another)
{return intersectCubeVsDisc(this, another); }
virtual bool intersectsVsCube(Cube *another)
{ return intersectCubeVsCube(this, another); }
};

Cast to derived class without unique_ptr

Background
I am creating a Cpp parser using Bison and Flex and I stumbled upon a problem: In my parser, I require a vector of base class objects, let's say shapes. Depending on which derived class an object has, I need to access different members. Thus, my intend was to store unique_ptr in the vector. Then upon access, I could dynamically cast them to their derived type.
The Problem
However, I can't get Bison to handle the unique_ptrs correctly. No matter how I specify the parser.yy file, upon compilation I run into errors like
usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
According to this post Bison does not handle unique_ptrs well (as far as I understand Bison does not use std::move() internally) and I assume that this is still the case.
My Question
As I would like to keep the class hierarchy as it is and don't want to fix bugs within Bison itself: Is there an alternative to using unique_ptrs when casting from Base class to Derived class?
Code Example
In particular, I want something like the following to work without using unique_ptrs.
enum Shape_type{
SHAPE_TYPE_CIRCLE,
SHAPE_TYPE_TRIANGLE,
};
class Shape{
public:
enum Shape_type type;
Shape(enum Shape_type type){ this->type=type; }
virtual ~Shape(){}
};
class Circle: public Shape{
int r;
public:
int get_r(){ return this->r; }
Circle(int r):Shape(SHAPE_TYPE_CIRCLE){ this->r=r; }
};
int main(void){
std::vector<std::unique_ptr<Shape>> shapes;
std::unique_ptr<Shape> circle_ptr = std::make_unique<Circle>(42);
shapes.push_back(std::move(circle_ptr));
for(auto& s_ptr: shapes){
switch(s_ptr->type){
case SHAPE_TYPE_CIRCLE:
{
auto c = dynamic_cast<Circle&>(*s_ptr);
std::cout << "circle with r=" << c.get_r() << std::endl;
break;
}
default: {
std::cout << "other shape" << std::endl;
break;
}
}
}
return 0;
}
Any help is greately appreciated. Thanks in advance.
The polymorphic way would be (replacing non-copiable std::unique_ptr by std::shared_ptr):
class Shape{
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
};
class Circle: public Shape
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const override { std::cout << "circle with r=" << r << std::endl; }
};
class Square: public Shape
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const override { std::cout << "square with side=" << side << std::endl; }
};
int main()
{
std::vector<std::shared_ptr<Shape>> shapes { std::make_shared<Circle>(42) };
for (const auto& shape_ptr: shapes)
{
shape_ptr->draw();
}
return 0;
}
With std::variant, you might do
class Circle
{
int r;
public:
explicit Circle(int r): r(r) {}
int get_r() const { return r; }
void draw() const { std::cout << "circle with r=" << r << std::endl; }
};
class Square
{
int side;
public:
explicit Square(int side): side(side) {}
int get_side() const { return side; }
void draw() const { std::cout << "square with side=" << side << std::endl; }
};
using Shape = std::variant<Circle, Square>;
int main()
{
std::vector<Shape> shapes { Circle(42) };
for (const auto& shape: shapes)
{
std::visit([](const auto& shape){ shape.draw(); }, shape);
}
return 0;
}

Operator == Overload for Derived Classes in C++

I am writing a program that has different shape classes
There is a base shape class similar to the following:
class Shape
{
public:
Shape(int x, int y, int size, COLORREF colorRef);
~Shape();
bool operator == (const Shape&) const;
int x() const;
int y() const;
int size() const;
protected:
int xCoord;
int yCoord;
int shapeSize;
COLORREF color;
};
And then some derived classes similar to the following:
class Circle : public Shape
{
public:
Circle(int x, int y, int size, COLORREF colorRef) : Shape(x, y, size, colorRef)
{
this->radius = (double)shapeSize / 2;
this->xCenter = (double)xCoord + radius;
this->yCenter = (double)yCoord - radius;
}
~Circle() {}
private:
double radius;
double xCenter;
double yCenter;
};
class Square : public Shape
{
public:
Square(int x, int y, int size, COLORREF colorRef) : Shape(x, y, size, colorRef) {}
~Square() {}
};
class Triangle : public Shape
{
public:
Triangle(int x, int y, int size, COLORREF colorRef) : Shape(x, y, size, colorRef) {}
~Triangle() {}
};
I would like to overload the == operator in the shape class so that I can determine if 2 shapes are identical. If I could assume both shapes being compared were of the same class then I know it would be fairly straight forward, but how do I go about testing whether 2 objects of the different derived classes are equal? For example, how do I determine that Triangle t != Circle c?
You have to determine which function to call based on type of two objects. This pattern in C++ is called double-dispatch (or Visitor pattern).
The most common implementation assumes that all derived classes (shapes in your example) are known - so you can list them in base class:
class Circle;
class Rectangle;
// all shapes here
class Shape {
public:
virtual ~Shape() = default; // good habit is to add virtual destructor to all polymorphic classes (those with virtual methods)
bool operator == (const Shape& other) const {
return equalTo(other);
}
virtual bool equalTo(const Shape& other) const = 0;
virtual bool doEqualTo(const Circle& other) const { return false; }
virtual bool doEqualTo(const Rectangle& other) const { return false; }
// etc.. for all other shapes
};
class Circle : public Shape {
// ...
protected:
virtual bool equalTo(const Shape& other) const
{
return other.doEqualTo(*this); // call doEqualTo(Circle) - first virtual dispatch
}
virtual bool doEqualTo(const Circle& other) const
{
return other.center == center && other.radius == radius; // second virtual dispatch
}
};
As you can see - to perform action - you have to call 2 virtual functions (so double-dispatch)
Ok, here's an idea for using the curious recurring template pattern to make implementing derived classes easier while allowing the == operator to work as expected. This maybe overkill, but it should work for your scenario.
Start by filling out your base Shape class. Added to your basic definition is an implementation of operator== that invokes a helper called CompareTypesAndDimensions. The function calls into two virtual methods, TypeCompare and Compare.
class Shape
{
public:
Shape(int x, int y, int size, COLORREF colorRef) : xCoord(x), yCoord(y), shapeSize(size), color(colorRef) {}
virtual ~Shape() {}; // need at least one virtual member for dynamic_cast
int x() const { return xCoord; }
int y() const { return yCoord; }
int size() const { return shapeSize; }
COLORREF col() const { return color; };
bool operator == (const Shape& other) const
{
return CompareTypesAndDimensions(other);
}
bool BaseShapeCompare(const Shape& other) const
{
return ((other.xCoord == xCoord) && (other.yCoord == yCoord) && (other.shapeSize == shapeSize) && (other.color == color));
}
virtual bool TypeCompare(const Shape& other) const = 0;
virtual bool Compare(const Shape& other) const = 0;
bool CompareTypesAndDimensions(const Shape& other) const
{
// make sure the types checks are reciprocals
// we don't accidently compare a "Square" with a "Rectangle" if they inherit from each other
if (TypeCompare(other))
{
return Compare(other);
}
return false;
}
protected:
int xCoord;
int yCoord;
int shapeSize;
COLORREF color;
};
The idea being with the above is that Circle, Triangle, and Square could just implement their own version of TypeCompare and Compare and be done with it. But wait! What if we could save some typing by having a template base class do some work for us - especially for validating that both compared instances are of the same type. And not having to a stock Compare function for the simpler types such as Square and Triangle.
Let's introduce a template class that inherits from Shape. This class, ShapeComparable provides the implementations for Compare and TypeCompare. The only thing it needs the concrete class below it to deal with is a method to handle comparing its own methods.
template <typename T>
class ShapeComparable : public Shape
{
public:
ShapeComparable(int x, int y, int size, COLORREF colorRef) : Shape(x, y,size,colorRef)
{}
bool TypeCompare(const Shape& other) const override
{
auto pOtherCastToDerived = dynamic_cast<const T*>(&other);
return (pOtherCastToDerived != nullptr);
}
bool Compare(const Shape& other) const override
{
if (BaseShapeCompare(other))
{
auto pOtherCastToDerived = dynamic_cast<const T*>(&other);
if (pOtherCastToDerived)
{
return this->CompareDerived(*pOtherCastToDerived);
}
}
return false;
}
// derived classes that don't have members to compare will just inherit this member
virtual bool CompareDerived(const T& other) const
{
return true;
}
};
The magic with the above is that TypeCompare utilizes a dynamic_cast to validate if the two instances being compared are of the same type. If you try to compare a Triangle to a Circle, the dynamic cast fails. Hence, operator== will return false.
Now let's see what the rest of the classes look like. Start with Circle, it inherits from ShapeComparable and provides an implementation for CompareDerived.
class Circle : public ShapeComparable<Circle>
{
public:
Circle(int x, int y, int size, COLORREF colorRef) : ShapeComparable(x,y,size,colorRef)
{
this->radius = (double)shapeSize / 2;
this->xCenter = (double)xCoord + radius;
this->yCenter = (double)yCoord - radius;
}
bool CompareDerived(const Circle& other) const
{
// BaseCompare has already been invoked by the time this method is invoked.
return ((other.radius == radius) && (other.xCenter == xCenter) && (other.yCenter == yCenter));
}
private:
double radius;
double xCenter;
double yCenter;
};
But Triangle and Square are as simple as it gets.
class Triangle : public ShapeComparable<Triangle>
{
public:
Triangle(int x, int y, int size, COLORREF colorRef) : ShapeComparable(x, y, size, colorRef) {}
};
class Square : public ShapeComparable<Square>
{
Square(int x, int y, int size, COLORREF colorRef) : ShapeComparable(x, y, size, colorRef) {}
};
And if you ever need to introduce a new property to Triangle and Square, you just need to provide a CompareDerived method.
The above works with the assumption is that you wouldn't have additional shapes derived from another concrete shape class. Otherwise, the CompareType function won't be reciprocal when comparing a Square to a Rhombus.

How to instantiate abstract child class with parent class

I'm trying to make a Chess game, and I'm having difficulties with creating the objects. My thought process went something like this:
Create a game board with 64 tiles, the tiles would have their own position and a pointer to a piece, thus I would be able to "easily" load in and unload a piece.
Tile class:
class Tile {
private:
int x;
int y;
Piece* piece;
public:
Tile(int x, int y) {
this->x = x;
this->y = y;
piece = nullptr;
}
void loadTile(Piece piece) {
this->piece = new Piece(piece); //this gives an error
}
void unloadTile() {
delete this->piece;
}
};
The individual pieces would then inherit from a parent class (below you can see a dumbed-down version). Inherited pieces would all have the same constructor and they would only differ in the way they calculate the possible moves. This, in my mind, is the best scenario to use a virtual function.
Piece and pawn class:
class Piece {
protected:
int x;
int y;
public:
Piece(int x, int y) {
this->x = x;
this->y = y;
}
virtual vector<int> returnPossibleMoves() = 0;
};
class Pawn : public Piece {
public:
using Piece::Piece;
vector<int> returnPossibleMoves() {
vector<int> moves;
moves.push_back(10); //dont think about this too much
return moves;
}
};
And here is the problem - the loadTile() function cannot instantiate the piece object because it is abstract.
I can see that my code may not work because I try to instantiate Piece with Pawn, but I don't really know how I would make it work, or what the workaround for this is. Hopefully you will be able to see what I'm trying to go for.
To strictly answer the question: you cannot create instances of abstract classes. That's why new Piece is not allowed. You would have to create an instance of a derived type that is not abstract, such as Pawn, and assign the piece pointer to point to that:
void Tile::loadTile() {
this->piece = new Pawn; //this is allowed
}
There are clearly some design changes that you'll need to make with this in mind, some of which have been mentioned in the comments on your question.
The Tile don't know which Piece type to instantiate, this is the fundamental problem.
What about something like this? (Disclaim, I just implemented some ideas, the code need probably lot of improvements until to get to sufficient quality)
#include <array>
#include <cassert>
#include <memory>
#include <vector>
using namespace std;
class Piece;
using CPiecePtr = std::shared_ptr<const Piece>;
enum class PieceType
{
Pawn
};
class Pos
{
int m_x=0;
int m_y=0;
public:
Pos()=default;
Pos(const Pos&)=default;
Pos& operator=(const Pos&)=default;
Pos( int x, int y): m_x(x), m_y(y)
{
assert(x>=0 && x<8 && y>=0 && y<8);
}
int x() const { return m_x; }
int y() const { return m_y; }
};
class Move
{
Pos m_origin;
Pos m_destination;
public:
Move()=default;
Move(const Move&)=default;
Move& operator=(const Move&)=default;
Move( const Pos& orig, const Pos& dest): m_origin(orig), m_destination(dest){}
const Pos& getDestination() const { return m_destination; }
const Pos& getOrigin() const { return m_origin; }
};
using MoveSet = std::vector<Move>;
class Tile
{
private:
CPiecePtr m_piece;
public:
void loadTile(CPiecePtr piece)
{
m_piece = piece;
}
void unloadTile()
{
m_piece = nullptr;
}
void setPiece(CPiecePtr piece) // this is more generic than previous two functions
{
m_piece = piece;
}
CPiecePtr getPiece() const
{
return m_piece;
}
};
class Piece
{
PieceType m_type;
public:
virtual MoveSet returnPossibleMoves(const Pos&) const = 0;
Piece(): m_type(PieceType::Pawn){}
PieceType getType() const { return m_type; }
};
class Pawn : public Piece
{
public:
MoveSet returnPossibleMoves(const Pos& pos) const override
{
MoveSet moves;
moves.push_back(Move(pos, Pos(pos.x(), pos.y()+1)));
//...
//TODO how to manage special moves? King-rook, replace pawn at end line...
return moves;
}
};
class Chess
{
private:
std::array<std::array<Tile,8>,8> m_board;
std::vector<CPiecePtr> m_pieces;
public:
Chess()
{
m_pieces.push_back( std::make_shared<const Pawn>());
//...
setPieceAt(Pos(0,1), m_pieces[0]);
}
CPiecePtr getPieceAt( const Pos& pos) const
{
return m_board[pos.x()][pos.y()].getPiece();
}
void setPieceAt( const Pos& pos, CPiecePtr piece)
{
return m_board[pos.x()][pos.y()].setPiece(piece);
}
// example:
MoveSet getMoveSetForPos( const Pos& pos)
{
const auto& piecePtr = getPieceAt(pos);
if (nullptr != piecePtr)
{
return piecePtr->returnPossibleMoves(pos);
}
return {};
}
void movePiece( const Move& move)
{
const auto& prevPiece = getPieceAt(move.getOrigin());
const auto& nextPiece = getPieceAt(move.getDestination());
assert(prevPiece && !nextPiece);
setPieceAt(move.getDestination(), prevPiece);
setPieceAt(move.getOrigin(), nullptr);
}
};
int main()
{
Chess chess;
const auto& moves = chess.getMoveSetForPos(Pos(0,1));
if (moves.size()>0)
{
chess.movePiece(moves[0]);
}
assert( chess.getPieceAt(Pos(0,2))->getType() == PieceType::Pawn);
return 0;
}
EDIT: I was not very proud of the answer, so I edited the code to make it compile. However, a fully working Chess is more complex than that, I leave how to manage king-rook and other special moves to the reader.

Why can't this derived object access the base class' post-decrement method?

class Player
{
private:
int score;
public:
Player(int number);
~Player();
int get_score() { return score; }
Player& operator--();
};
Player::Player(int number)
{
score = number;
}
Player::~Player()
{
}
//-----
//Please turn your attention to this function
//-----
Player& Player::operator--() {
score--;
return *this;
}
Hello all, in the above class, I have overloaded the post-decrement operator to decrease the 'score'. There are two sub classes derived from this class - Computer and Human. From my understanding, they should also have access to this function. However, when I try:
Computer comp_; Human player_;
comp--;
human--;
I get an error saying: 'neither of these classes define this operator or a conversion to a type accessible to the predefined operator'. I am not allowed to redefine this function within the sub classes.
It would really help if someone could help me figure out how to get this code working! <3
You're trying to use the post-decrement operator, but you've declared the pre-decrement operator!
To make this code work, either use pre-decrement comp--; => --comp;. Or switch to defining the post-decrement operator Player& operator--(); => Player& operator--(int);. See a working example here: ideone.
For more on what each decrement/increment operator looks like, see the cppreference page.
The post decrement operator should look like this:
T T::operator--(int); // Inside class definition
T operator++(T& a, int); // Outside class definition
and it's supposed to return a copy of the object like it looked before you decreased its value.
class Player
{
private:
int score;
public:
Player(int number);
virtual ~Player();
int get_score() { return score; }
template<typename T>
friend T& operator--(T& p) { // pre
--p.score;
return p;
}
};
Player::Player(int number) : score(number) {}
Player::~Player() {}
template<typename T>
T operator--(T& p, int) { // post
T save(p);
--p; // using pre
return save;
}
The problem comes from the fact that you only define pre-increment operator.
see https://en.cppreference.com/w/cpp/language/operator_incdec
The pre-increment returns a reference, however the post increment returns a value therefore if you need to retain the type of the object returned. I would define the post-increment as a template and use the implementation of the pre-increment.
namespace Game
{
class Player
{
private:
int score;
public:
Player(int number);
~Player();
int get_score() { return score; }
Player& operator--();
};
Player::Player(int number)
{
score = number;
}
Player::~Player()
{
}
Player& Player::operator--() {
score--;
return *this;
}
template <class T> T operator--(const T& a, int)
{
T save(a);
save--;
return save;
}
class Human : public Player
{
public:
Human(int player) :Player(player) {}
};
class Computer : public Player
{
public:
Computer(int player) :Player(player) {}
};
}
example
int main()
{
Game::Human h(2);
Game::Human h2 = h--;
}