19

Consider this program:

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

When I try to compile and build this in Debug mode Visual Studio 2017 is generating these compiler errors:

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 ==========

However, when I try this under Release mode: It compiles, builds, runs, and produces the appropriate output:

10
adds called on line 12
14

Is this a potential Visual Studio 2017 bug? If not, why does it work in one mode and not the other?

You can see it compiled here: Compiler Explorer


Here's a copy of the command line flags for both debug and release modes:

Debug

/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 

Release

/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 
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59

1 Answers1

22

Seems like it was reported: __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.

And Jonathan says:

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 ...

From 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:

I guess the reason for it is the /ZI vs /Zi flag difference. Your release mode flags have /Zi so it compiles fine.

Waqar
  • 8,558
  • 4
  • 35
  • 43
  • 1
    Nice to know! It's one of those rare things you run into... but good to know! All be it, this won't be too much of a bother anymore once C++20 is fully supported and completely mainstream! – Francis Cugler Jul 13 '20 at 07:00
  • 1
    @FrancisCugler -- You mean [std::source_location](https://en.cppreference.com/w/cpp/utility/source_location)? – PaulMcKenzie Jul 13 '20 at 07:05
  • The odd thing to this "potential or unofficial bug" is, I've always had `/Zi` and `/ZI` set by default and never changed them going as far back as Visual Studio 2003... or since whenever they introduced the Continue & Edit feature... and this is the first time I've ever encountered this " 'non-bug' - 'side-effect feature' " by MSVC... There is a "Standard" to keep compilers and code bases compliant with a specific behavior or set of semantics that the language is supposed to provide... Microsoft: "We're 95% compliant" in keeping true to the standard... – Francis Cugler Jul 13 '20 at 07:16
  • @PaulMcKenzie Yes, can't wait to rebuild my PC again... I'm still using Windows 7, and I'm a bit reluctant to go to Windows 10... kind of dreading it... However, when I finally do rebuild it, I'll be installing Visual Studio 2019 for C++20 support... can't wait for that at least. If worst comes to worst, I might just have to install Cygwin again and install gcc within that environment for C++20... but I'm not use to gcc's compiler and linking flags... I'm too accustomed to Visual Studio... But yes, I was referring to `std::source_location`! – Francis Cugler Jul 13 '20 at 07:24
  • 1
    there's also clang if you want to try (you can use it inside VS). I hear good things about it ;) – Waqar Jul 13 '20 at 07:26
  • 1
    @Waqar Well I'm also using Python and JavaScript for other things... I just like the power, control, and efficiency of C++ for backend library codebases... And yes changing the `/ZI` to `/Zi` in debug mode fixed the problem... And to be honest I'm not even sure if I ever utilized the `Edit and Continue` feature... and I have built working 3D graphics - game engines from scratch using OpenGL and DirectX and started to learn Vulkan. My current hobby project is trying to build a Circuit Simulator from Scratch! I've already done hardware emulation (NES)... – Francis Cugler Jul 13 '20 at 07:33
  • @Waqar At one time Intel's compiler was reverted as being fairly good... Well, I'm not sure exactly which compiler they were using, but they had their own IDE so I'm assuming they have their own compiler, linker, and debugger... I've always had Intel architectures, however, I've never had their compiler or IDE because it was never freely available to the public it was always proprietary and wasn't cheap. I'm not sure about now as that could have changed... I'd have to look into it. https://software.intel.com/content/www/us/en/develop/tools/compilers/c-compilers/choose-download.html – Francis Cugler Jul 13 '20 at 16:28
  • 1
    @FrancisCugler I mentioned [clang](https://clang.llvm.org/), which is freely available. Yeah ICC(intel compiler) is not freely available, though they give a free license for FOSS projects(not sure about this either). It supposedly produces faster code for intel architectures(haven't tried yet so can't be sure) – Waqar Jul 13 '20 at 16:59
  • 1
    @FrancisCugler: Given that the Standard does not and cannot require that implementations be capable of processing any non-trivial range of source files as a condition of conformance, conformance should be defined in terms of rejecting programs that cannot be processed according to the Standard, rather than requiring that implementations accept a wide range of programs unless they exceed potentially-undocumented combinations of translation limits, in which case implementations would be allowed to process them in completely arbitrary fashion. – supercat Jul 13 '20 at 20:53
  • 1
    @FrancisCugler: Under that philosophy, I'd regard VC's adherence to the Standard as much better than that of clang and gcc, which process in meaningless fashion source texts whose behavior is defined by the Standard in ways that don't fit the abstraction models used by clang and gcc. – supercat Jul 13 '20 at 20:54
  • @TonyK Maybe, but not necessarily... There are people who may rely on the Edit and Continue feature of Visual Studio's compiler. This has more to do with the construction and behavior of their product than it does to the actual standard of the language itself. Compiler vendors are free to implement their software as they see fit so as long as the generated object files or translations units themselves conform to the C++ language standard. Clang may do something one way, GCC in another, Visual Studio does it their way, and even Intel doing something completely different than the rest of them. – Francis Cugler Jul 14 '20 at 01:26