Inconsistent behaviour across compilers in regard to instantiation of a template in a discarded if...
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++17
flag): compiles fine;
✓ GCC (version 8.2, with-std=c++17
flag): also compiles fine;
❌ MSVC (version 19.16, with/std:c++17
flag): 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/includeoptional(87): error C2182: '_Value': illegal use of type 'void'
C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]
Live demo
c++ language-lawyer c++17
add a comment |
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++17
flag): compiles fine;
✓ GCC (version 8.2, with-std=c++17
flag): also compiles fine;
❌ MSVC (version 19.16, with/std:c++17
flag): 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/includeoptional(87): error C2182: '_Value': illegal use of type 'void'
C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]
Live demo
c++ language-lawyer c++17
2
Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.
– Dan M.
18 hours ago
For what it's worth: the motivation ofif constexpr
was more or less exactly to make examples like that compile.
– Barry
12 hours ago
add a comment |
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++17
flag): compiles fine;
✓ GCC (version 8.2, with-std=c++17
flag): also compiles fine;
❌ MSVC (version 19.16, with/std:c++17
flag): 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/includeoptional(87): error C2182: '_Value': illegal use of type 'void'
C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]
Live demo
c++ language-lawyer c++17
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++17
flag): compiles fine;
✓ GCC (version 8.2, with-std=c++17
flag): also compiles fine;
❌ MSVC (version 19.16, with/std:c++17
flag): 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/includeoptional(87): error C2182: '_Value': illegal use of type 'void'
C:/msvc/v19_16/includeoptional(128): note: see reference to class template instantiation 'std::_Optional_destruct_base<_Ty,false>' being compiled
with
[
_Ty=void
]
Live demo
c++ language-lawyer c++17
c++ language-lawyer c++17
edited 17 hours ago
YSC
21.1k34797
21.1k34797
asked 18 hours ago
NejcNejc
758212
758212
2
Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.
– Dan M.
18 hours ago
For what it's worth: the motivation ofif constexpr
was more or less exactly to make examples like that compile.
– Barry
12 hours ago
add a comment |
2
Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.
– Dan M.
18 hours ago
For what it's worth: the motivation ofif constexpr
was more or less exactly to make examples like that compile.
– Barry
12 hours ago
2
2
Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.
– Dan M.
18 hours ago
Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.
– Dan M.
18 hours ago
For what it's worth: the motivation of
if constexpr
was more or less exactly to make examples like that compile.– Barry
12 hours ago
For what it's worth: the motivation of
if constexpr
was more or less exactly to make examples like that compile.– Barry
12 hours ago
add a comment |
2 Answers
2
active
oldest
votes
Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.
if constexpr
is standardized in [stmt.if]/2
:
If the
if
statement is of the formif constexpr
, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.
This applies.
If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].
It also applies, making in your program { std::optional<T> val; }
a discarded statement.
During the instantiation of an enclosing templated entity (ndYSC
Bar<void, int>
), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.
add a comment |
Along with @YSC's answer, also relevant is [temp.inst]/10
:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54126957%2finconsistent-behaviour-across-compilers-in-regard-to-instantiation-of-a-template%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.
if constexpr
is standardized in [stmt.if]/2
:
If the
if
statement is of the formif constexpr
, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.
This applies.
If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].
It also applies, making in your program { std::optional<T> val; }
a discarded statement.
During the instantiation of an enclosing templated entity (ndYSC
Bar<void, int>
), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.
add a comment |
Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.
if constexpr
is standardized in [stmt.if]/2
:
If the
if
statement is of the formif constexpr
, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.
This applies.
If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].
It also applies, making in your program { std::optional<T> val; }
a discarded statement.
During the instantiation of an enclosing templated entity (ndYSC
Bar<void, int>
), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.
add a comment |
Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.
if constexpr
is standardized in [stmt.if]/2
:
If the
if
statement is of the formif constexpr
, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.
This applies.
If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].
It also applies, making in your program { std::optional<T> val; }
a discarded statement.
During the instantiation of an enclosing templated entity (ndYSC
Bar<void, int>
), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.
Definitively a bug of MSVC. A bug report exist and has been reportedly fixed in Visual Studio 2019 Preview.
if constexpr
is standardized in [stmt.if]/2
:
If the
if
statement is of the formif constexpr
, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement.
This applies.
If the value of the converted condition is false, the first substatement is a discarded statement, otherwise [...].
It also applies, making in your program { std::optional<T> val; }
a discarded statement.
During the instantiation of an enclosing templated entity (ndYSC
Bar<void, int>
), if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.
edited 17 hours ago
answered 18 hours ago
YSCYSC
21.1k34797
21.1k34797
add a comment |
add a comment |
Along with @YSC's answer, also relevant is [temp.inst]/10
:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.
add a comment |
Along with @YSC's answer, also relevant is [temp.inst]/10
:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.
add a comment |
Along with @YSC's answer, also relevant is [temp.inst]/10
:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.
Along with @YSC's answer, also relevant is [temp.inst]/10
:
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement , unless such instantiation is required.
answered 17 hours ago
P.WP.W
11.8k3842
11.8k3842
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54126957%2finconsistent-behaviour-across-compilers-in-regard-to-instantiation-of-a-template%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Looks like an MSVC bug, since IRC the part under constexpr if shouldn't be instantiated if it depends on a template parameter, unless the branch was taken.
– Dan M.
18 hours ago
For what it's worth: the motivation of
if constexpr
was more or less exactly to make examples like that compile.– Barry
12 hours ago