为什么不允许使用'constexpr'参数?



拥有'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 check 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)'

如果我了解您尝试正确执行的操作,那么您请求的功能已经可用。这不是最优雅的,但我认为这已经足够好了。

您希望使用相同的语法在编译时和运行时调用函数,如果可能,请在编译时对其进行计算,否则应在运行时对其进行计算。无论何时调用函数,都需要对函数计算断言。

我相信这会做你想要的:

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的方式失败,并且在运行时也会失败。

虽然这在理论上听起来很棒,但在现实世界中并没有那么有用。函数的大多数参数都不是编译时常量,并且在编译时也不完全知道许多约束。

指定和实现这种重载将是一项大量的工作,并且不会使用那么多。当你实际有编译时间界限和参数时,你通常可以在编译时计算整个函数,这意味着不需要重载。

最新更新