“if constexpr()"之间的区别与“if()"

Difference between quot;if constexpr()quot; Vs quot;if()quot;(“if constexpr()之间的区别与“if())

本文介绍了“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::value) 将在编译时间,如果它是 true,那么所有其他分支(else ifelse)都会被丢弃.如果是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()"

基础教程推荐