I'm testing out user defined literals. I want to make _fac
return the factorial of the number.
Having it call a constexpr
function works, however it doesn't let me do it with templates as the compiler complains that the arguments are not and cannot be constexpr
.
I'm confused by this - aren't literals constant expressions? The 5
in 5_fac
is always a literal that can be evaluated during compile time, so why can't I use it as such?
First method:
constexpr int factorial_function(int x) {
return (x > 0) ? x * factorial_function(x - 1) : 1;
}
constexpr int operator "" _fac(unsigned long long x) {
return factorial_function(x); // this works
}
Second method:
template <int N> struct factorial_template {
static const unsigned int value = N * factorial_template<N - 1>::value;
};
template <> struct factorial_template<0> {
static const unsigned int value = 1;
};
constexpr int operator "" _fac(unsigned long long x) {
return factorial_template<x>::value; // doesn't work - x is not a constexpr
}
I may be wrong, but I think constexpr functions can also be called with non-constant arguments (in which case they don't give a constant expression and are evaluated at runtime). Which wouldn't work well with non-type template arguments.
I don't know if there's a better way in C++11 to do this than the current accepted answer, but with relaxed
constexpr
in C++14, you can just write "normal" code:In order to make use of constexpr with user defined literals, you apparently have to use a variadic template. Take a look at the second listing in the wikipedia article for an example.
This is how I ended up doing it:
Huge thanks to KerrekSB!
@Pubby. The easy way to digest the char non-type parameter pack is to cature it into an initializer list for a string. Then you can use atoi, atof, etc:
Remember to tack on a null character for the C-style functions.