I am trying to understand whether the snippet below should compile according to The Standard or not. When I try to compile it with latest version of three major compilers, the following occurs:
- ✓ Clang (version 7.0.0, with
-std=c++17flag): compiles fine; - ✓ GCC (version 8.2, with
-std=c++17flag): also compiles fine; - ❌ MSVC (version 19.16, with
/std:c++17flag): compiler error (see below).
The error occurs because the MSVC compiler seemingly tries to instantiate std::optional<void> despite the fact that the code is discarded. GCC and Clang don't seem to do that.
Does The Standard clearly define what should occur in this case?
#include <optional>
#include <type_traits>
template<typename T, typename... Args>
struct Bar
{
void foo(Args... args)
{
if constexpr(!std::is_same_v<T, void>) // false
{
// MSVC compiler error occurs because of the line below; no error occurs when compiling with GCC and Clang
std::optional<T> val;
}
}
};
int main(int argc, char** argv)
{
Bar<void, int> inst;
inst.foo(1);
return 0;
}
Error by MSVC:
C:/msvc/v19_16/include\optional(87): error C2182: '_Value': illegal use of type 'void' C:/msvc/v19_16/include\optional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled with [ _Ty=void ]