当前位置: 首页 > 知识库问答 >
问题:

"if stanexpr()"与"if()"的区别

王杰
2023-03-14

if constexpr()if()有什么区别?

我在哪里和什么时候可以使用这两种工具?

共有2个答案

桑成荫
2023-03-14

普通的if语句:

  • 是否在每次控制到达时评估其状态,如果有的话
  • 确定要执行的两个子语句中的哪一个,跳过另一个
  • 要求两个子语句都格式良好,无论在运行时实际选择哪个

if instexpr语句:

  • 在提供所有必要的模板参数后,是否在编译时对其条件进行求值
  • 确定要编译两个子语句中的哪一个子语句,丢弃另一个子语句
  • 不要求废弃的子语句格式正确
韦翰音
2023-03-14

唯一的区别是< code>if constexpr是在编译时计算的,而< code>if不是。这意味着分支可以在编译时被拒绝,因此永远不会被编译。

想象一下,你有一个函数long,它返回一个数字的长度,或者一个类型的长度,这个类型有一个. long()函数。你不能在一个函数中做到这一点,编译器会抱怨:

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
}

错误消息:

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();
            ~~~~^~~~~~

这是因为当编译器实例化长度时,函数将如下所示:

auto length(const int& value) noexcept {
    if (std::is_integral<int>::value) { // is number
        return value;
    else
        return value.length();
}

value是一个int,因此没有 member函数,因此编译器会抱怨。编译器看不到 int永远不会到达该语句,但这无关紧要,因为编译器不能保证这一点。

现在,您可以专门化长度,但是对于许多类型(例如在这种情况下 - 每个数字和类都有一个长度成员函数),这会导致大量重复的代码。SFINAE也是一种解决方案,但它需要多个函数定义,这使得代码比需要与下面的代码进行比较要长得多。

使用if constexpr代替if意味着分支(

template<typename T>
auto length(const T& value) noexcept {
    if constexpr (std::integral<T>::value) { // is number
        return value;
    else
        return value.length();
}

现在,当编译器将实例化long时,它将如下所示:

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 个重载是有效的,代码将成功编译。

 类似资料:
  • 问题内容: 我想知道为什么要使用一个语句而不是多个语句?例如,这样做之间有什么区别: 还有这个: 他们似乎做的完全一样。 问题答案:

  • 问题内容: 两者之间有什么区别吗? …和… ? 问题答案: 它们是相同的,但是如果您的代码中包含MVC并且不想在代码中产生大量回声,那么第二个方法就很棒。例如,在我的文件(Zend Framework)中,我将编写如下内容:

  • 本文向大家介绍如何区分vue中的v-show 与 v-if,包括了如何区分vue中的v-show 与 v-if的使用技巧和注意事项,需要的朋友参考一下 1. v-show 不管初始的条件是什么,元素总是会被渲染,并且只是简单的基于 CSS display: none 或者 display: block 的属性进行切换。 2. v-if 会根据初始的条件(data里自己的定义的数据)来进行真正的渲染

  • 问题内容: List listStr = new ArrayList (); 与 在我看来,使用的好处之一是它不检查列表的大小,然后将其与零进行比较,它只是检查列表是否为空。是否有任何其他的优点,因为我经常看到的,而不是在代码库?是否存在我不知道以这种方式检查的原因? 问题答案: 基本上,在某些列表的实现中,该方法检查大小是否为零(因此从性能的角度来看,它们实际上是等效的)。但是,在其他类型的列表

  • 本文向大家介绍if-else和switch之间的区别,包括了if-else和switch之间的区别的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们将了解if-else语句和'switch'语句之间的区别。 if-else 根据语句中的表达式,将生成输出。 它对多个选择使用多个语句。 该语句测试是否相等。 它可以用来测试逻辑表达式。 它可以计算整数,字符,指针,浮点类型和布尔类型。 仅执行“

  • 问题内容: 给定以下代码段,有什么明显的区别? 与 还是单出口原则在这段代码中会更好… 有没有明显的性能差异?您是否觉得其中一个比另一个更可维护/可读? 问题答案: 在第二个示例中,您非常清楚地指出两个条件是互斥的。 对于第一个,并不清楚,并且在(不太可能)的事件中,在两个if之间添加to的分配,逻辑将发生变化。 假设将来有人在第二个if之前添加。 当然,这不太可能发生,但是如果我们在这里谈论可维