msc*_*msc 21 c++ if-statement constexpr c++17
if constexpr()和之间有什么区别if()?
我何时何地可以同时使用它们?
Rak*_*111 27
唯一的区别是if constexpr在编译时进行评估,而if不是.这意味着在编译时可以拒绝分支,因此永远不会编译.
想象一下,你有一个函数,length它返回一个数字的长度,或者一个具有.length()函数的类型的长度.你不能在一个函数中执行它,编译器会抱怨:
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) << '\n'; // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
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();
~~~~^~~~~~
Run Code Online (Sandbox Code Playgroud)
那是因为当编译器实例化时length,该函数将如下所示:
auto length(const int& value) noexcept {
if (std::is_integral<int>::value) { // is number
return value;
else
return value.length();
}
Run Code Online (Sandbox Code Playgroud)
value是一个int,因此没有length成员函数,所以编译器抱怨.编译器无法看到永远不会达到该语句int,但无关紧要,因为编译器无法保证.
现在你可以专门化length,但是对于很多类型(比如在这种情况下 - 每个数字和带有length成员函数的类),这会产生大量重复的代码.SFINAE也是一个解决方案,但它需要多个函数定义,这使得代码比下面需要的代码要长很多.
使用if constexpr而不是if意味着branch(std::is_integral<T>::value)将在编译时得到评估,如果是,true那么每个其他分支(else if和else)都会被丢弃.如果是false,则检查下一个分支(这里else),如果是true,则丢弃每个其他分支,依此类推......
template<typename T>
auto length(const T& value) noexcept {
if constexpr (std::integral<T>::value) { // is number
return value;
else
return value.length();
}
Run Code Online (Sandbox Code Playgroud)
现在,当编译器实例化时length,它将如下所示:
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();
}
Run Code Online (Sandbox Code Playgroud)
所以这两个重载是有效的,代码将成功编译.
Bri*_*ian 24
普通的if语句:
if constexpr声明: