为什么这段使用 __LINE__ 的代码在 MSVC 下以 Release 模式编译,而不是在 Debug 模式下编译?
Why does this code using __LINE__ compile under MSVC in Release mode, but not in Debug mode?
考虑这个程序:
#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
好像有人报道过:__LINE__
cannot be used as an argument for constexpr functions.
We have a known bug for this issue on the C++ team here.
[...]
We have determined that this issue is not a bug. Please refer to comments of Jonathan.
乔纳森说:
This is a side-effect of the compilers support for Edit-and-Continue (basically we don't want a change to the value of __LINE__
to be considered a 'rude' edit that suppresses Edit-and-Continue): if you compiler with /Zi
instead of /ZI
then the code should compile (but the executable won't support Edit-and-Continue).
[...]
The bug is considered a feature ...
来自 MSVC docs:
The /ZI
option is similar to /Zi
, but it produces a PDB file in a format that supports the Edit and Continue feature. [...] The /ZI
option is also incompatible with use of the __LINE__
predefined macro; code compiled with /ZI
can't use __LINE__
as a non-type template argument, although __LINE__
can be used in macro expansions.
However, when I try this under Release mode: It compiles, builds, runs, and produces the appropriate output:
我猜这是因为 /ZI
与 /Zi
标志的不同。您的发布模式标志具有 /Zi
,因此可以正常编译。
考虑这个程序:
#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
好像有人报道过:__LINE__
cannot be used as an argument for constexpr functions.
We have a known bug for this issue on the C++ team here.
[...]
We have determined that this issue is not a bug. Please refer to comments of Jonathan.
乔纳森说:
This is a side-effect of the compilers support for Edit-and-Continue (basically we don't want a change to the value of
__LINE__
to be considered a 'rude' edit that suppresses Edit-and-Continue): if you compiler with/Zi
instead of/ZI
then the code should compile (but the executable won't support Edit-and-Continue).
[...]
The bug is considered a feature ...
来自 MSVC docs:
The
/ZI
option is similar to/Zi
, but it produces a PDB file in a format that supports the Edit and Continue feature. [...] The/ZI
option is also incompatible with use of the__LINE__
predefined macro; code compiled with/ZI
can't use__LINE__
as a non-type template argument, although__LINE__
can be used in macro expansions.
However, when I try this under Release mode: It compiles, builds, runs, and produces the appropriate output:
我猜这是因为 /ZI
与 /Zi
标志的不同。您的发布模式标志具有 /Zi
,因此可以正常编译。