使用delete防止C 14中使用无效的值呼叫



我可以使用模板并删除功能,以防止具有字符或浮点变量的呼叫阶乘,如下所示。如何编写带有负面参数的阶乘的删除函数?

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?
}

不可能。= delete是编译时的内容,而您的参数并不总是在编译时间中所知。

您可以改用unsigned参数,然后删除所有删除的过载,以无法用签名的数字来调用您的功能,例如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)));
}

如何编写带负论点的阶乘的删除函数?

您不能,因为参数的值是运行时属性,但您只能基于类型删除过载。

,但由于这是constexpr,因此有另一种方法 - 您只需使函数不构建恒定表达式中的负输入。例如,通过投掷。另外,由于您标记了此C 14,因此我将您的实现更改为一个循环:

template <typename T>
constexpr T factorial(T n)
{
    if (n < 0) throw std::runtime_error("bad user!");
    T product = 1;
    for (T i = 2; i <= n; ++i) {
        product *= i;
    }
    return product;
}
constexpr auto good = factorial(5); // fine
constexpr auto bad = factorial(-1); // compile error because factorial(-1)
                                    // is not a valid constant expression

最新更新