首页 > 解决方案 > 我需要把 constexpr 放在 else-if 之后吗?

问题描述

受此答案的启发,我尝试复制并粘贴(并在其中添加测试main())此代码:

template<typename T>
std::tuple<int, double> foo(T a) {
    if constexpr (std::is_same_v<int, T>)
        return {a, 0.0};
    else if (std::is_same_v<double, T>)
        return {0, a};
    else
        return {0, 0.0};
}

int main() {
    auto [x, y] = foo("");
    std::cout << x << " " << y;
}

这很简单——如果T推断为int,我们想要返回一个 的元组[a, 0.0]。如果T推导为double,我们要返回 的元组 [0, a]。否则,我们要返回[0, 0.0]

如您所见,在main()函数中,我foo使用const char*参数调用,这应该导致xandy0. 事实并非如此

在尝试编译它时,我遇到了一个奇怪的错误:

错误: 无法将 ' {0, a}' 从 ' <brace-enclosed initializer list>' 转换为 ' std::tuple<int, double>'

我就像什么?. 为什么我会想要那个...我专门用于当类型被推断为时才std::is_same启用。return {0, a} adouble

所以我迅速跑到if-constexpr 上的cppreference。在页面底部的Notes上方,我们可以看到这段代码:

extern int x; // no definition of x required
int f() {
if constexpr (true)
    return 0;
else if (x)
    return x;
else
    return -x;
}

我心想oookay..?我真的看不出原始代码有什么问题。它们使用相同的语法和语义......

但我很好奇。我很好奇(当时)是否有一些奇怪的东西可以解决这个问题,所以我将原始代码更改为:

template<typename T>
std::tuple<int, double> foo(T a) {
    if constexpr (std::is_same_v<int, T>)
        return {a, 0.0};
    else if constexpr (std::is_same_v<double, T>) // notice the additional constexpr here
        return {0, a};
    else
        return {0, 0.0};
}

int main() {
    auto [x, y] = foo("");
    std::cout << x << " " << y;
}

瞧!代码按预期编译和执行。所以,我的问题是——在这种情况下,我们是否需要constexpr在每条if语句之后加上语句?if-else或者它只是我的编译器?我正在使用 GCC 7.3。

标签: c++if-statementc++17if-constexpr

解决方案


在这种情况下,我们是否需要在 if-else 块中的每个 if 语句之后放置 constexpr?

是的。else-if 块1是一个谎言 :),只有 if 块1和 else 块1。这是编译器看到您的代码的方式:

if constexpr (std::is_same_v<int, T>)
    return {a, 0.0};
else // {
    if (std::is_same_v<double, T>)
        return {0, a};
    else
        return {0, 0.0};
// }

else if (/*...*/)只是每个人都使用的格式约定。因此,您可以清楚地看到constexpr需要第二个。


1:“块”不是正确的术语。if 是一个语句(带有可选的 else 部分)。一个块是{ /*...*/ }.


推荐阅读