【发布时间】:2018-03-19 08:19:45
【问题描述】:
这段代码应该在编译时使用模板元编程检查浮点数是否等于整数的一半: #包括
struct A {
constexpr static bool value = true;
};
struct B {
constexpr static bool value = false;
};
template<int i>
struct Meta {
constexpr static int value = i/2;
constexpr static bool func(float n) {
return std::conditional_t<n==value,A,B>::value;
}
};
int main( int argc, const char *argv[] ) {
constexpr bool b = Meta<4>::func(2);
std::cout << b << std::endl;
return 0;
}
但它拒绝编译。编译器说n is not a constant expression:
test.cpp: In substitution of ‘template<bool _Cond, class _Iftrue, class _Iffalse> using conditional_t = typename std::conditional::type [with bool _Cond = (n == (float)2); _Iftrue = A; _Iffalse = B]’:
test.cpp:15:50: required from ‘static constexpr int Meta<i>::func(float) [with int i = 4]’
test.cpp:21:36: required from here
test.cpp:15:50: error: ‘n’ is not a constant expression
return std::conditional_t<n==value,A,B>::value;
^~~~~
test.cpp:15:50: note: in template argument for type ‘bool’
test.cpp: In function ‘int main(int, const char**)’:
test.cpp:21:36: in constexpr expansion of ‘Meta<4>::func((float)2)’
test.cpp:21:38: error: constexpr call flows off the end of the function
constexpr int b = Meta<4>::func(2);
^
这里有什么问题?传递给Meta::func 的值是文字值。它应该被视为一个常量。
我感兴趣的是如何在编译时根据值执行不同的操作。这应该是可能的,因为计算输出所需的所有输入都在编译时可用。
我想知道如何在编译时根据值执行不同的操作(可能涉及类型)。这应该是可能的,因为计算输出所需的所有输入都在编译时可用。
【问题讨论】:
-
constexpr函数仍然是一个常规函数,可以在运行时使用任意n调用。那么if constexpr将如何处理呢? -
在调用函数时使用了字面量整数值,但在函数内部它不再是字面量而是普通变量。 “传递”文字值的唯一方法是将
func设为非类型模板,并将n作为模板参数。这不适用于浮点类型。 -
@StoryTeller 如帖子所述,我希望在编译时计算该值。我正在尝试了解模板实例化如何与此代码一起使用。
-
在不相关的说明中,您知道浮点比较的相等性几乎没有用吗?
-
@saga 浮点计算总是存在可能发生舍入的问题。进行两次不同的计算(有时甚至使用不同的值进行相同的计算)在数学上应该会产生相同的结果,但由于四舍五入的影响,可能会得到两个不完全相同的值。这就是为什么您不应该比较浮点值是否完全相等,而是因为它们的差异足够小......
标签: c++ templates metaprogramming template-meta-programming