我需要在 else-if 之后放置 constexpr 吗?

Do I need to put constexpr after 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,我们想要return一个[a, 0.0]的元组。如果T被推导为double,我们想要return一个[0, a]的元组。否则,我们要 return [0, 0.0].

如您所见,在 main() 函数中,我使用 const char* 参数调用 foo 应该 导致 xy0。那是不是这样

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

error: could not convert '{0, a}' from '<brace-enclosed initializer list>' to 'std::tuple<int, double>'

我当时想 什么?。我到底为什么要那个...我专门使用 std::is_same 来启用 return {0, a} 只有 a 的类型被推断为 double.

所以我很快 运行 cppreference 在 if-constexpr 上。在页面底部 Notes 上方,我们可以看到这段代码:

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

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

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

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;
}

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

Do we need to put constexpr after every if statement in if-else block in these kind of situations?

是的。 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:"block" 不是正确的术语。 if 是一个语句(带有可选的 else 部分)。一个块是{ /*...*/ }.