grains: template version

This commit is contained in:
Dmitry Kokorin 2016-03-16 20:57:50 +03:00
parent 1e20c23729
commit 2aa26a8950
2 changed files with 51 additions and 62 deletions

View file

@ -1,56 +0,0 @@
#include "grains.h"
#include <limits>
#include <stdexcept>
namespace grains {
using namespace std;
namespace {
static const index_t number_of_squares = 64;
template <typename T>
struct total_as_max
{
static inline T total()
{
return numeric_limits<T>::max();
}
};
template <typename T>
struct total_by_shift
{
static inline T total()
{
return T(1) << number_of_squares - 1;
}
};
static_assert(number_of_squares <= numeric_limits<ulong_t>::digits,
"grains::ulong_t is too small for grains::total");
typedef conditional<number_of_squares == numeric_limits<ulong_t>::digits,
total_as_max<ulong_t>,
total_by_shift<ulong_t>>::type total_policy_t;
}
ulong_t square(index_t index)
{
if (index < 1 || index > number_of_squares)
throw domain_error("invalid square number");
return ulong_t(1) << (index - 1);
}
ulong_t total()
{
return total_policy_t::total();
}
}

View file

@ -3,12 +3,57 @@
#define EXERCISM_RUN_ALL_TESTS
namespace grains {
#include <limits>
#include <stdexcept>
typedef unsigned long long ulong_t;
typedef unsigned int index_t;
ulong_t square(index_t index);
ulong_t total();
template <size_t number_of_squares = 64,
typename ulong_t = unsigned long long>
class custom_grains
{
typedef typename std::numeric_limits<ulong_t> limits_t;
}
static_assert(std::is_unsigned<ulong_t>::value,
"ulong_t must be unsigned");
static_assert(number_of_squares <= limits_t::digits,
"ulong_t is too short");
struct total_as_max
{
static inline ulong_t total()
{
return limits_t::max();
}
};
struct total_by_shift
{
static inline ulong_t total()
{
return ulong_t(1) << number_of_squares - 1;
}
};
typedef typename std::conditional<
number_of_squares == limits_t::digits,
total_as_max,
total_by_shift>::type total_policy_t;
public:
static ulong_t square(size_t index)
{
if (index < 1 || index > number_of_squares)
throw std::domain_error("invalid square number");
return ulong_t(1) << (index - 1);
}
static ulong_t total()
{
return total_policy_t::total();
}
};
typedef custom_grains<> grains;