Since C+11 we have generalized constants, i.e. constexpr
Constexpr variable
- immediately constructed or assigned
- must contain only literal values, constexpr variables and functions
- the constructor used must be constexpr constructor
Constexpr function
- must not be virtual
- return type must be LiteralType
- parameters must be literal type
- body must be either deleted or defaulted or contain only the following:
null statements
static_assert declarations
typedef declarations and alias declarations that do not define classes or enumerations
using declarations
using directives
C++11: exactly one return statement
C++14: -
Constexpr constructor
- parameters must be literal type
- must have no virtual base classes
- either deleted or defaulted or contain only the following:
...as above...
- the constructor must not have a function-try block
- base class and every non-static member must be initialized
- every implicit conversion involved must be a constant expression
Constexpr functions can be called with all constexpr parameter values
- the return value can be assigned to a constexpr variable
or non constexpr values
- the return value can be assigned to non-constexpr variable
constexpr int pow( int base, int exp) noexcept
{
return exp == 0 ? 1 : base * pow(base, exp-1) ;
}
constexpr int pow( int base, int exp) noexcept
{
auto result = 1;
for (int i = 0; i < exp; ++i) result *= base;
return result;
}
#include <iostream>
constexpr int strlen(const char *s)
{
const char *p = s;
while ( '\0' != *p ) ++p;
return p-s;
}
int main()
{
std::cout << strlen("Hello") << std::endl;
return 0;
}
#include <iostream>
#include <stdexcept>
class conststr {
const char * p;
std::size_t sz;
public:
template<std::size_t N>
constexpr conststr(const char(&a)[N]) : p(a), sz(N-1) {}
constexpr char operator[](std::size_t n) {
return n < sz ? p[n] : throw std::out_of_range("");
}
constexpr std::size_t size() { return sz; }
};
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
std::size_t c = 0) {
return n == s.size() ? c :
s[n] >= 'a' && s[n] <= 'z' ? countlower(s, n+1, c+1) :
countlower(s, n+1, c);
}
template<int n> struct constN {
constN() { std::cout << n << '\n'; }
};
int main()
{
std::cout << "Number of lowercase letters in \"Hello, world!\" is ";
constN<countlower("Hello, world!")> out2;
}
class Point
{
public:
constexpr Point(double xVal = 0, double yVal = 0) noexcept
: x(xVal), y(yVal) {}
constexpr double xValue() const noexcept { return x; }
constexpr double yValue() const noexcept { return y; }
constexpr void setX(double newX) noexcept { x = newX; }
constexpr void setY(double newY) noexcept { y = newY; }
private:
double x, y;
};
constexpr Point p1(42.0, -33.33);
constexpr Point p2(25.0, 33.3);
constexpr Point midpoint(const Point& p1, const Point& p2) noexcept
{
return { (p1.xValue() + p2.xValue()) / 2,
(p1.yValue() + p2.yValue()) / 2 };
}
constexpr auto mid = midpoint(p1, p2);
constexpr Point reflection(const Point& p) noexcept
{
Point result;
result.setX(-p.xValue());
result.setY(-p.yValue());
return result;
}
constexpr auto midReflected = reflection(mid);
Template metaprograms only emulates floating point vales.