C++ 使用delete防止在C++;14
我可以使用模板和delete工具来防止使用字符或浮点变量调用factorial,如下所示。如何为带负参数的阶乘编写delete函数C++ 使用delete防止在C++;14,c++,c++14,constexpr,factorial,C++,C++14,Constexpr,Factorial,我可以使用模板和delete工具来防止使用字符或浮点变量调用factorial,如下所示。如何为带负参数的阶乘编写delete函数 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 facto
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?
}
模板
constexpr T阶乘(tn)
{
返回(n==1 | | n==0)?1:(n*阶乘(n-1));
}
constexpr float factorial(double)=删除;
constexpr char factorial(char)=delete;
int main()
{
constexpr auto-fiveFactorial=阶乘(5);
constexpr auto point5fact=factorial(0.5);//错误。调用已删除的版本
constexpr auto letter5fact=factorial('5');//同上
constexpr auto minusFact=factorial(-1);//如何使用delete防止这种情况?
}
不可能=delete
是编译时的事情,而您的参数在编译时并不总是已知的
您可以改为使用unsigned
参数并删除所有已删除的重载,代价是无法使用有符号数字调用函数,如factorial(2)
template constexpr T阶乘(tn)
{
静态断言(std::is_unsigned_v&&!std::is_same_v,
“参数类型必须是整数、无符号,而不是'char'”;
返回(n==1 | | n==0)?1:(n*阶乘(T(n-1));
}
不可能=delete
是编译时的事情,而您的参数在编译时并不总是已知的
您可以改为使用unsigned
参数并删除所有已删除的重载,代价是无法使用有符号数字调用函数,如factorial(2)
template constexpr T阶乘(tn)
{
静态断言(std::is_unsigned_v&&!std::is_same_v,
“参数类型必须是整数、无符号,而不是'char'”;
返回(n==1 | | n==0)?1:(n*阶乘(T(n-1));
}
如何为带负参数的阶乘编写delete函数
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?
}
不能,因为参数的值是运行时属性,但只能删除基于类型的重载
但由于这是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
模板
constexpr T阶乘(tn)
{
如果(n<0)抛出std::runtime_错误(“坏用户!”);
T积=1;
对于(ti=2;i
如何为带负参数的阶乘编写delete函数
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?
}
不能,因为参数的值是运行时属性,但只能删除基于类型的重载
但由于这是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
模板
constexpr T阶乘(tn)
{
如果(n<0)抛出std::runtime_错误(“坏用户!”);
T积=1;
对于(ti=2;i您不能,因为该值是在运行时计算的。类型也可以,因为它们在编译时是已知的,但是您不能得到只有在运行时才知道的编译器错误。我能看到的唯一解决方案是确保T
是无符号类型。如果您只想允许无符号整数类型,是指仅声明泛型函数而不实现它(或者甚至可能将其标记为已删除?)。然后使用定义(实现)专门化无符号整数类型的函数。您不能这样做,因为该值是在运行时计算的。类型也可以,因为它们在编译时是已知的,但您无法获取仅在运行时已知的内容的编译器错误。我看到的唯一解决方案是确保t
是无符号类型。作为另一种可能的解决方案,如果您只想允许unsigned整数类型,就是只声明泛型函数而不实现它(或者甚至可能将它标记为已删除?)。然后用定义(实现)专门化无符号整数类型的函数。OP的factorial(5)
当然不再适用于此。如果OP对此没有问题,可以,但我认为它可以使用拼写。但现在需要调整实现:递归调用必须是阶乘(n-1u)
,否则调用阶乘(5us)
(具有无符号短值5的调用)将失败,因为5us-1
的类型是int
,它不是无符号的。@SebastianRedl Done.:/OP的阶乘(5)
当然不再适用于此。如果OP对此没有问题,可以,但我认为它可以使用拼写。但现在需要调整实现:递归调用必须是阶乘(n-1u)
,否则调用阶乘(5us)
(具有无符号短值5的调用)将失败,因为5us-1
的类型为int
,它不是无符号的。@SebastianRedl Done.:/