base: Use constexpr in Cycles

Declare the constructor and all of the operators that don't change the
state of a Cycles instance as constexpr. This makes it possible to use
Cycles as a static constant and allows the compiler to evaulate simple
expressions at compile time. An unfortunate side-effect of this is
that we cannot use assertions since C++11 doesn't support them in
constexpr functions. As a workaround, we throw an invalid_argument
exception when the assert would have triggered. A nice side-effect of
this is that the compiler will evaluate the "assertion" at compile
time when an expression involving Cycles can be statically evaluated.
This commit is contained in:
Andreas Sandberg 2015-08-07 09:59:12 +01:00
parent 83a668ad25
commit 3e26756f1d

View file

@ -42,6 +42,7 @@
#include <cassert>
#include <memory>
#include <ostream>
#include <stdexcept>
#include "base/refcnt.hh"
@ -90,8 +91,12 @@ class Cycles
public:
#ifndef SWIG // SWIG gets confused by constexpr
/** Explicit constructor assigning a value. */
explicit constexpr Cycles(uint64_t _c) : c(_c) { }
#else
explicit Cycles(uint64_t _c) : c(_c) { }
#endif
/** Default constructor for parameter classes. */
Cycles() : c(0) { }
@ -99,7 +104,7 @@ class Cycles
#ifndef SWIG // keep the operators away from SWIG
/** Converting back to the value type. */
operator uint64_t() const { return c; }
constexpr operator uint64_t() const { return c; }
/** Prefix increment operator. */
Cycles& operator++()
@ -110,23 +115,26 @@ class Cycles
{ assert(c != 0); --c; return *this; }
/** In-place addition of cycles. */
const Cycles& operator+=(const Cycles& cc)
Cycles& operator+=(const Cycles& cc)
{ c += cc.c; return *this; }
/** Greater than comparison used for > Cycles(0). */
bool operator>(const Cycles& cc) const
constexpr bool operator>(const Cycles& cc) const
{ return c > cc.c; }
const Cycles operator +(const Cycles& b) const
constexpr Cycles operator +(const Cycles& b) const
{ return Cycles(c + b.c); }
const Cycles operator -(const Cycles& b) const
{ assert(c >= b.c); return Cycles(c - b.c); }
constexpr Cycles operator -(const Cycles& b) const
{
return c >= b.c ? Cycles(c - b.c) :
throw std::invalid_argument("RHS cycle value larger than LHS");
}
const Cycles operator <<(const int32_t shift)
constexpr Cycles operator <<(const int32_t shift) const
{ return Cycles(c << shift); }
const Cycles operator >>(const int32_t shift)
constexpr Cycles operator >>(const int32_t shift) const
{ return Cycles(c >> shift); }
friend std::ostream& operator<<(std::ostream &out, const Cycles & cycles);