Version 1
One template parameter, LoadedDie that can return two values.
Version 2
In this version, the Dice Game takes two template parameters. Notice that because of this, we cannot put them into a vector.
DiceGame_TwoTemplateParametersTest.h
#include <CppUTest/TestHarness.h>
#include "DiceGame_TwoTemplateParameters.h"
template<int v1>
class HardCodedDie {
public:
void roll() {}
int faceValue() {
return v1;
}
};
TEST_GROUP(DiceGame_TwoTemplateParameters) { };
TEST(DiceGame_TwoTemplateParameters, WinningShouldIncreaeBalance) {
DiceGame_TwoTemplateParameters<HardCodedDie<4>> diceGame;
diceGame.play();
LONGS_EQUAL(1, diceGame.getBalance());
}
TEST(DiceGame_TwoTemplateParameters, LosingShouldDecreaseBalance) {
DiceGame_TwoTemplateParameters<HardCodedDie<3>> diceGame;
diceGame.play();
LONGS_EQUAL(-1, diceGame.getBalance());
}
TEST(DiceGame_TwoTemplateParameters, PushShouldLeaveBalanceUnchanged) {
DiceGame_TwoTemplateParameters<HardCodedDie<3>, HardCodedDie<4>> diceGame;
diceGame.play();
LONGS_EQUAL(0, diceGame.getBalance());
}
DiceGame_TwoTemplateParameters.h
#pragma once
#include "Die.h"
#include <vector>
template<class T1=Die, class T2=T1>
class DiceGame_TwoTemplateParameters {
public:
DiceGame_TwoTemplateParameters();
~DiceGame_TwoTemplateParameters();
void play();
int getBalance() const { return balance; }
private:
T1 d1;
T2 d2;
int balance;
};
template<class T1, class T2>
DiceGame_TwoTemplateParameters<T1, T2>::DiceGame_TwoTemplateParameters() : balance(0) {
}
template<class T1, class T2>
DiceGame_TwoTemplateParameters<T1, T2>::~DiceGame_TwoTemplateParameters() {
}
template<class T1, class T2>
void DiceGame_TwoTemplateParameters<T1, T2>::play() {
d1.roll();
d2.roll();
int total = d1.faceValue() + d2.faceValue();
if(total > 7)
++balance;
else if(total < 7)
--balance;
}
Version 3
In this version, the LoadedDie are instead “LoadedDieWithTwoAlternatinvValues”, where the two values are template parameters. The DiceGame takes one template parameter. DiceGame_UsingTemplatesTest.cpp
#include <CppUTest/TestHarness.h>
#include "DiceGame_UsingTemplates.h"
template<int v1, int v2 = v1>
class LoadedDieWithTwoAlternativingValues {
public:
LoadedDieWithTwoAlternativingValues() {
values[0] = v1;
values[1] = v2;
}
void roll() {}
int faceValue() {
return values[++count%2];
}
private:
static int count;
int values[2];
};
template<int v1, int v2> int LoadedDieWithTwoAlternativingValues<v1, v2>::count = -1;
TEST_GROUP(DiceGame_UsingTemplates) { };
TEST(DiceGame_UsingTemplates, WinningShouldIncreaeBalance) {
DiceGame_UsingTemplates<LoadedDieWithTwoAlternativingValues<4>> diceGame;
diceGame.play();
LONGS_EQUAL(1, diceGame.getBalance());
}
TEST(DiceGame_UsingTemplates, LosingShouldDecreaseBalance) {
DiceGame_UsingTemplates<LoadedDieWithTwoAlternativingValues<3>> diceGame;
diceGame.play();
LONGS_EQUAL(-1, diceGame.getBalance());
}
TEST(DiceGame_UsingTemplates, PushShouldLeaveBalanceUnchanged) {
DiceGame_UsingTemplates<LoadedDieWithTwoAlternativingValues<3, 4>> diceGame;
diceGame.play();
LONGS_EQUAL(0, diceGame.getBalance());
}
DiceGame_UsingTemplates.h
#pragma once
#include "Die.h"
#include <vector>
template<class T=Die>
class DiceGame_UsingTemplates {
public:
DiceGame_UsingTemplates();
~DiceGame_UsingTemplates();
void play();
int getBalance() const { return balance; }
private:
typedef std::vector<T> DiceCollection;
DiceCollection dice;
int balance;
};
template<class T>
DiceGame_UsingTemplates<T>::DiceGame_UsingTemplates() : balance(0) {
dice.push_back(T());
dice.push_back(T());
}
template<class T>
DiceGame_UsingTemplates<T>::~DiceGame_UsingTemplates() {
}
#include <tr1/functional>
#include <numeric>
using namespace std;
using namespace tr1;
using namespace placeholders;
template<class T>
void DiceGame_UsingTemplates<T>::play() {
for_each(dice.begin(), dice.end(), bind(&T::roll, _1));
int total = accumulate(dice.begin(), dice.end(), 0, bind(plus<int>(), _1, bind(&T::faceValue, _2)));
if(total > 7)
++balance;
else if(total < 7)
--balance;
}
Comments