拥有' constexpr'参数,以区分编译器已知的值,以便能够在编译时检测错误。例子:
int do_something(constexpr int x)
{
static_assert(x > 0, "x must be > 0");
return x + 5;
}
int do_something(int x)
{
if(x > 0) { cout << "x must be > 0" << endl; exit(-1); }
return x + 5;
}
int var;
do_something(9); //instance 'do_something(constexpr int x)' and check arg validity at compile-time
do_something(0); //produces compiler-error
do_something(var); //instance 'do_something(int x)'
现在这是无效的代码。有人可以解释一下为什么不能这样做吗?
编辑:
使用模板用户应该确保文字总是作为模板参数传递,而不是作为非常不舒服的函数传递:
template<int x>
int do_something()
{
static_assert(x > 0, "x must be > 0");
return x + 5;
}
int do_something(int x)
{
if(x > 0) { cout << "x must be > 0" << endl; exit(-1); }
return x + 5;
}
int var;
do_something(9); //instance 'do_something(int x)' and doesn't checks validity at compile-time
do_something(0); //same as above, if check was performed - compiler error should occur
do_something<9>(); //instance template 'do_something<int>()'
do_something<0>(); //produces compiler error
do_something(var); //instance 'do_something(int x)'
答案 0 :(得分:3)
如果我了解您正在尝试正确执行的操作,则您要求的功能已经可用。它不是最优雅的,但我认为这已经足够了。
您希望在编译时和运行时使用相同的语法调用函数,并在可能的情况下在编译时进行评估,否则应在运行时进行评估。无论何时调用函数,都需要对函数进行求值。
我相信这会做你想做的事情:
constexpr int do_something(int x)
{
if(x <= 0)
{
std::cout << "x must be > 0" << std::endl; exit(-1);
}
return x + 5;
}
constexpr int compiletime_good = do_something(5);
constexpr int compiletime_bad = do_something(0); // Fails at compile-time
int runtime_good = do_something(5);
int runtime_bad = do_something(0); // Fails at runtime
constexpr int val_good = 5;
constexpr int val_bad = 0;
do_something(val_good);
do_something(val_bad); // Fails at run-time
int valrun_good = 5;
int valrun_bad = 0;
do_something(valrun_good);
do_something(valrun_bad); // Fails at run-time
这里的诀窍是在编译时以不需要static_assert的方式失败,并且在运行时也会失败。
答案 1 :(得分:-4)
虽然这在理论上听起来很棒,但它在现实世界中并没有那么有用。函数的大多数参数都不是编译时常量,并且许多约束在编译时也不是完全已知的。
指定和实现这样的重载将是一项重要的工作,并且它不会被那么多地使用。当您实际拥有编译时边界和参数时,通常可以在编译时评估整个函数,这意味着不需要重载。