类型推导如何用于评估表达式?

时间:2015-08-19 02:44:12

标签: c++ templates compilation

我刚刚使用模板进行了钳制功能。它看起来像这样:

template <typename Tp_, typename Up_, typename Vp_>
inline auto clamp(Tp_ x, Up_ xmin, Vp_ xmax)
noexcept -> decltype(x < xmin ? xmin : (x > xmax ? xmax : x)) {
  return x < xmin ? xmin : (x > xmax ? xmax : x);
}

template <typename Tp_, typename Up_>
inline auto clamp(Tp_ x, const Up_ &v) -> decltype(clamp(x, min(v),
                                                         max(v))) {
  static_assert(is_iterable<Up_>::value,
                "The data set must be iterable");
  return clamp(x, min(v), max(v));
}

我有一个测试该功能的单元测试:

TEST(StatsTest, clamp) {
  ASSERT_EQ(clamp(1, 0, 5), 1);
  ASSERT_EQ(clamp(-1, 0, 3), 0);
  ASSERT_EQ(clamp(15, 0, 3), 3);

  ASSERT_EQ(clamp(1, 0.f, 3.), 1);
  ASSERT_EQ(clamp(-1, 0.f, 3.), 0.f);
  ASSERT_EQ(clamp(15, 0, 3), 3.);

  ASSERT_EQ(clamp(543, v1), 543);
  ASSERT_EQ(clamp(-143, v1), 71);
  ASSERT_EQ(clamp(14143, v1), 977);
}

但是当我考虑它时,这没有意义:decltype(clamp(x, min(v), max(v)))的结果在运行时之前不应该被人知道,是吗?

以防万一,我试图用一些变量数据替换我的测试:

TEST(StatsTest, clamp) {
  int a = 0;
  float b = 65.3f;
  double c = 89.7;
  ASSERT_EQ(clamp(a, b, c), 65.3f);
}

但它仍然过去了!

解释是什么?

2 个答案:

答案 0 :(得分:1)

clamp返回的类型是参数的常见类型,它不是所选参数的类型。

然后,您会被进一步的促销活动所欺骗,使您的平等检查成立。

decltype( true?7:3.0 )decltype( false?7:3.0 )的类型相同。

答案 1 :(得分:1)

一般情况下,你不能这样做。在这种情况下,这种方法的唯一原因是因为您正在使用具有默认转换的整数/浮点值。例如:

float f;
int y;
double z;
std::cin >> f;
std::cin >> y;
std::cin >> z;
auto p = clamp(f, y, z);
static_assert(std::is_same<decltype(p), double>::value, "Not Double!");

这样可行,因为所有给定的类型都可以升级为double。一般情况下,如果您尝试使用没有此类促销的类型执行此操作,则会出现编译时错误,因为必须在编译时知道函数的返回类型(当然必须是,否则编译器如何知道在堆栈上为返回值分配多少空间?)。