Search code examples
c++c++14constexprfactorial

Using delete to prevent call with invalid values in C++14


I can use templates and delete facility to prevent calling factorial with character or float variables as follows. How to write the delete function for factorials with negative arguments?

template <typename T>
constexpr T factorial(T n)
{
    return (n == 1 || n == 0) ? 1 : (n * factorial(n - 1));
}

constexpr float factorial(double) = delete;
constexpr char factorial(char) = delete;

int main()
{
    constexpr auto fiveFactorial = factorial(5);
    constexpr auto point5fact = factorial(0.5); // Error. Call to deleted version
    constexpr auto letter5fact = factorial('5'); // DITTO
    constexpr auto minusFact = factorial(-1); // How to prevent this using delete?
}

Solution

  • Impossible. = delete is a compile-time thing, while your arguments aren't always known at compile-time.

    You could use unsigned parameter instead and remove all those deleted overloads, at the cost of being unable to call your function with signed numbers, like factorial(2).

    template <typename T> constexpr T factorial(T n)
    {
        static_assert(std::is_unsigned_v<T> && !std::is_same_v<T, char>,
                      "Parameter type must be integral, unsigned, and not `char`.");
        return (n == 1 || n == 0) ? 1 : (n * factorial(T(n - 1)));
    }