【问题标题】:Why does this code using __LINE__ compile under MSVC in Release mode, but not in Debug mode?为什么使用 __LINE__ 的这段代码在 MSVC 下可以在 Release 模式下编译,但不能在 Debug 模式下编译?
【发布时间】:2020-11-02 08:02:21
【问题描述】:

考虑这个程序:

#include <iostream>

template<bool Debug = false, int Line = __LINE__>
constexpr int adds(const int& a, const int& b) { 
    if (Debug)
        std::cout << __FUNCTION__ << " called on line " << Line << '\n';
    return (a + b);
}

int main() {
    std::cout << adds(3, 7) << '\n';
    std::cout << adds<true, __LINE__> (5, 9) << '\n';
    return 0;
}

当我尝试在 Debug 模式下编译和构建它时,Visual Studio 2017 正在生成这些编译器错误:

1>------ Build started: Project: Simulator, Configuration: Debug x64 ------
1>main2.cpp
1>c:\***\main2.cpp(12): error C2672: 'adds': no matching overloaded function found
1>c:\***\main2.cpp(12): error C2975: 'Line': invalid template argument for 'adds', expected compile-time constant expression
1>c:\***\main2.cpp(3): note: see declaration of 'Line'
1>Done building project "Simulator.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

但是,当我在Release 模式下尝试此操作时:它会编译、构建、运行并产生适当的输出:

10
adds called on line 12
14

这是一个潜在的 Visual Studio 2017 错误吗?如果不是,为什么它在一种模式下工作而不是另一种模式?

你可以在这里看到它的编译:Compiler Explorer


这是调试和发布模式的命令行标志的副本:

调试

/JMC /permissive- /GS /W3 /Zc:wchar_t /Qspectre /ZI /Gm- /Od /sdl /Fd"x64\Debug\vc141.pdb" /Zc:inline /fp:precise /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /std:c++latest /FC /Fa"x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\Simulator.pch" /diagnostics:classic 

发布

/permissive- /GS /GL /W3 /Gy /Zc:wchar_t /Qspectre /Zi /Gm- /O2 /sdl /Fd"x64\Release\vc141.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oi /MD /std:c++latest /FC /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\Simulator.pch" /diagnostics:classic 

【问题讨论】:

  • 你能显示调试和发布配置吗? (即他们使用什么编译器标志)
  • @GuyIncognito 除了我将所有配置和平台的语言标志设置为 ISO C++ Latest Draft Standard (/std:c++latest) 之外,一切基本上都是标准的……其他一切都是 Visual Studio 的默认设置。
  • 酷,VS 默认是什么?
  • 可能是 C++ 编译器错误,但不是 Visual Studio 错误。

标签: c++ visual-c++ compiler-errors visual-studio-2017 compiler-bug


【解决方案1】:

好像被举报了:__LINE__ cannot be used as an argument for constexpr functions

我们在此处的 C++ 团队中有一个针对此问题的已知错误。
[...]
我们已确定此问题不是错误。请参考Jonathan的cmets。

乔纳森说:

这是编译器支持 Edit-and-Continue 的副作用(基本上我们不希望更改 __LINE__ 的值被认为是抑制 Edit-and-Continue 的“粗鲁”编辑): 如果您使用/Zi 而不是/ZI 进行编译,那么代码应该可以编译(但可执行文件不支持编辑并继续)。
[...]
该错误被认为是一项功能...

来自MSVC docs

/ZI 选项 类似于/Zi,但它生成的 PDB 文件格式支持“编辑并继续”功能。 [...] /ZI 选项也与 __LINE__ 预定义宏的使用不兼容;使用/ZI 编译的代码不能使用__LINE__ 作为非类型模板参数,尽管__LINE__ 可以用于宏扩展。


但是,当我在发布模式下尝试此操作时:它会编译、构建、运行并产生适当的输出:

我猜它的原因是 /ZI/Zi 标志的差异。你的发布模式标志有/Zi,所以它编译得很好。

【讨论】:

  • 很高兴知道!这是你遇到的那些罕见的事情之一......但很高兴知道!无论如何,一旦 C++20 得到完全支持并完全成为主流,这将不再是一件麻烦事!
  • @FrancisCugler -- 你的意思是std::source_location?
  • 如果你想尝试也有clang(你可以在VS内部使用它)。我听说了它的好消息;)
  • @Waqar 好吧,我还在将 Python 和 JavaScript 用于其他事情......我只是喜欢 C++ 用于后端库代码库的功能、控制和效率......并且是的,改变了 @987654339 @ to /Zi 在调试模式下解决了这个问题......老实说,我什至不确定我是否曾经使用过Edit and Continue 功能......而且我已经构建了工作3D图形 - 使用OpenGL从头开始的游戏引擎和 DirectX 并开始学习 Vulkan。我目前的爱好项目是尝试从头开始构建电路模拟器!我已经完成了硬件仿真(NES)...
  • @FrancisCugler 我提到了clang,它是免费提供的。是的,ICC(英特尔编译器)不是免费提供的,尽管他们为 FOSS 项目提供免费许可证(对此也不确定)。据说它可以为英特尔架构生成更快的代码(还没有尝试过,所以不能确定)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多