Difference between quot;if constexpr()quot; Vs quot;if()quot;(“if constexpr()之间的区别与“if())
问题描述
if constexpr()
和 if()
有什么区别?
我可以在何时何地同时使用它们?
Where and When can I use both of them?
推荐答案
唯一的区别是 if constexpr
在编译时被评估,而 if
不是.这意味着分支可以在编译时被拒绝,因此永远不会被编译.
The only difference is that if constexpr
is evaluated at compile time, whereas if
is not. This means that branches can be rejected at compile time, and thus will never get compiled.
假设你有一个函数,length
,它返回一个数字的长度,或者一个具有 .length()
函数的类型的长度.你不能在一个函数中做到,编译器会抱怨:
Imagine you have a function, length
, that returns the length of a number, or the length of a type that has a .length()
function. You can't do it in one function, the compiler will complain:
template<typename T>
auto length(const T& value) noexcept {
if (std::integral<T>::value) { // is number
return value;
else
return value.length();
}
int main() noexcept {
int a = 5;
std::string b = "foo";
std::cout << length(a) << ' ' << length(b) << '
'; // doesn't compile
}
错误信息:
main.cpp: In instantiation of 'auto length(const T&) [with T = int]':
main.cpp:16:26: required from here
main.cpp:9:16: error: request for member 'length' in 'val', which is of non-class type 'const int'
return val.length();
~~~~^~~~~~
那是因为当编译器实例化length
时,函数会是这样的:
That's because when the compiler instantiates length
, the function will look like this:
auto length(const int& value) noexcept {
if (std::is_integral<int>::value) { // is number
return value;
else
return value.length();
}
value
是一个 int
,因此没有 length
成员函数,因此编译器会抱怨.编译器看不到 int
永远不会到达该语句,但这无关紧要,因为编译器无法保证.
value
is an int
, and as such doesn't have a length
member function, and so the compiler complains. The compiler can't see that statement will never be reached for an int
, but it doesn't matter, as the compiler can't guarantee that.
现在你可以特化 length
,但是对于很多类型(比如在这种情况下 - 每个数字和具有 length
成员函数的类),这会导致很多重复的代码.SFINAE 也是一个解决方案,但是它需要多个函数定义,这使得代码比下面需要的要长很多.
Now you can either specialize length
, but for a lot of types (like in this case - every number and class with a length
member function), this results in a lot of duplicated code. SFINAE is also a solution, but it requires multiple function definitions, which makes the code a lot longer than it needs to be compared to the below.
使用 if constexpr
而不是 if
意味着分支 (std::is_integral
) 将在编译时间,如果它是 true
,那么所有其他分支(else if
和 else
)都会被丢弃.如果是false
,则检查下一个分支(这里是else
),如果是true
,则丢弃所有其他分支,依此类推...
Using if constexpr
instead of if
means that the branch (std::is_integral<T>::value
) will get evaluated at compile time, and if it is true
then every other branch (else if
and else
) gets discarded. If it is false
, the next branch is checked (here else
), and if it is true
, discard every other branch, and so on...
template<typename T>
auto length(const T& value) noexcept {
if constexpr (std::integral<T>::value) { // is number
return value;
else
return value.length();
}
现在,当编译器实例化length
时,它看起来像这样:
Now, when the compiler will instantiate length
, it will look like this:
int length(const int& value) noexcept {
//if (std::is_integral<int>::value) { this branch is taken
return value;
//else discarded
// return value.length(); discarded
}
std::size_t length(const std::string& value) noexcept {
//if (std::is_integral<int>::value) { discarded
// return value; discarded
//else this branch is taken
return value.length();
}
所以这 2 个重载是有效的,代码将成功编译.
And so those 2 overloads are valid, and the code will compile successfully.
这篇关于“if constexpr()"之间的区别与“if()"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:“if constexpr()"之间的区别与“if()"
基础教程推荐
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 从 std::cin 读取密码 2021-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- Windows Media Foundation 录制音频 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01