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
#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;
}
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>
#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;
}