c++ - `if constexpr`,lambda 内部,包扩展内部——编译器错误?

标签 c++ language-lawyer c++17 clang++ compiler-bug

clang version 5.0.0 (trunk 305664)
Target: x86_64-unknown-linux-gnu

以下代码编译成功:

template <int... A>
void f() {
    ([](auto) {
        if constexpr (A == 0)
            return 42;
        else
            return 3.14;
    }(0), ...);
}

int main() {
    f<0, 1>();
}

...但是这个没有:

template <int... A>
void f() {
    ([](auto...) {            // Variadic lambda
        if constexpr (A == 0)
            return 42;
        else
            return 3.14;
    }(), ...);                // No argument
}

int main() {
    f<0, 1>();
}

...屈服:

<source>:7:13: error: 'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement
            return 3.14;
            ^
<source>:3:6: note: in instantiation of function template specialization 'f()::(anonymous class)::operator()<>' requested here
    ([](auto...) {            // Variadic lambda
     ^
<source>:12:5: note: in instantiation of function template specialization 'f<0, 1>' requested here
    f<0, 1>();
    ^

我不希望空参数包和伪参数之间有不同的行为。

这种差异是有原因的,还是编译器错误?

最佳答案

我相信这是一个 clang 错误。

[dcl.spec.auto] 中的规则是,强调我的:

If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discarded return statements, if any, in the body of the function ([stmt.if]).

[...]

If a function with a declared return type that contains a placeholder type has multiple non-discarded return statements, the return type is deduced for each such return statement. If the type deduced is not the same in each deduction, the program is ill-formed.

lambda 中的一个或另一个 return 语句被丢弃(if constexpr 中未采用的分支称为 丢弃语句) ,它只留下一个未丢弃的 return 语句,因此 lambda 的返回类型应该简单地从剩下的那个中推导出来。

此外,clang 可以这样处理:

template <int A>
void f() {
    [](auto...) {
        if constexpr (A == 0)
            return 42;
        else
            return 3.14;
    }();
}

int main() {  
    f<0>();
    f<1>();
}

所以这可能与 lambda 在包表达式中的工作方式有一些不好的交互。

关于c++ - `if constexpr`,lambda 内部,包扩展内部——编译器错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44641253/

相关文章:

c++ - 如何将宏扩展的结果分成不同的参数?

c++ - 不死物体 ([basic.life]/8) : why is reference rebinding (and const modification) allowed?

C++17 iterator_traits 没有被调用

c++ - 如何检测构造函数是否真的是 constexpr,以便我可以使用静态初始化?

c++ - 如何在 C++ 中读取不断增长的文本文件?

C++/CLI UTF-8 和 JNI 无法正确转换 Unicode 字符串

c++ - Opencv C++ 调整大小函数 : new Width should be multiplied by 3

c++ - 演绎指南、模板和子对象 : which compiler is right?

c++ - 没有 return 语句到达函数末尾

c++17 - 升级到 Visual Studio 2019 和 v142 工具集后,为什么我的程序不再在 Windows 7 上运行?