我是否需要将constexpr放在else-if之后?

时间:2018-09-16 16:52:01

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

this answer的启发,我试图复制并粘贴(并在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*应该产生xy0。情况并非如此。

在尝试对其进行编译时,遇到一个奇怪的错误:

  

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

我就像什么?。我到底为什么要...我专门使用std::is_same来启用return {0, a} ,当将a的类型推导为double

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

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

瞧瞧!该代码按预期方式编译和执行。因此,我的问题是-在这种情况下,我们需要在constexpr语句中的每个if语句之后放置if-else吗?还是仅仅是我的编译器?我正在使用GCC 7.3。

1 个答案:

答案 0 :(得分:43)

  

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

是的。 else-if块 1 是一个谎言:),仅当blocks 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部分)。阻止为{ /*...*/ }