首页 > 解决方案 > 如何使用实值函数参数进行编译时错误检查?

问题描述

是否可以将 static_assert (或类似的东西)与真正有价值的函数参数一起使用?我想要做的是以下。在我的应用程序中,参数minmax将始终保持不变。理想情况下,我想将它们用作模板参数,但这样做是不可能的,因为它们是真正有价值的。使用 static_assert 的动机是我想进行编译时错误检查。

template <typename counts_t, typename real_t>
real_t counts2real(counts_t c, real_t min, real_t max)
{
  constexpr real_t cmin = std::numeric_limits<counts_t>::min();
  constexpr real_t cmax = std::numeric_limits<counts_t>::max();
  constexpr real_t cdelta = (cmax - cmin);

  // ERROR: non-constant condition for static assertion.
  static_assert(max > min, "max > min");

  real_t delta = (max - min);
  real_t p = (c - cmin) / cdelta;

  return (p * delta + min);
}

int16_t x = 0;
const float min = 10.0;
const float max = 5.0;

float xf = counts2real<int16_t,float>(x, min, max);

标签: c++c++11

解决方案


虽然floats 不能用作模板参数,但float const&s 可以。因此,您可以传递minmax作为模板参数:

template <typename real_t, real_t const& min, real_t const& max, typename counts_t>
real_t counts2real(counts_t c)
{
  constexpr real_t cmin = std::numeric_limits<counts_t>::min();
  constexpr real_t cmax = std::numeric_limits<counts_t>::max();
  constexpr real_t cdelta = (cmax - cmin);

  static_assert(max > min, "max > min");

  real_t delta = (max - min);
  real_t p = (c - cmin) / cdelta;

  return (p * delta + min);
}

用法:

constexpr float min = 10.0;
constexpr float max = 50.0;

float foo(int16_t x) {
    return counts2real<float, min, max>(x);
}

根据需要更改max5.0导致诊断:

<source>:13:21: error: static assertion failed: max > min
   static_assert(max > min, "max > min");

演示


在 C++17 中,您可以避免指定minand的类型max

template <auto const& min, auto const& max, typename counts_t>
constexpr auto counts2real(counts_t c)
{
  ...
}

// ...
float foo(int16_t x) {
    return counts2real<min, max>(x);
}

推荐阅读