在 C++14 中使用 delete 防止调用无效值
Using delete to prevent call with invalid values in 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)));
}
How to write the delete function for factorials with negative arguments?
你不能,因为参数的值是一个运行时 属性 但你只能删除基于类型的重载。
但由于这是 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
我可以使用模板和删除工具来防止使用字符或浮点变量调用阶乘,如下所示。如何为带负参数的阶乘编写删除函数?
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)));
}
How to write the delete function for factorials with negative arguments?
你不能,因为参数的值是一个运行时 属性 但你只能删除基于类型的重载。
但由于这是 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