我刚刚使用模板进行了钳制功能。它看起来像这样:
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);
}
但它仍然过去了!
解释是什么?
答案 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
。一般情况下,如果您尝试使用没有此类促销的类型执行此操作,则会出现编译时错误,因为必须在编译时知道函数的返回类型(当然必须是,否则编译器如何知道在堆栈上为返回值分配多少空间?)。