Should this code fail to compile in C++17?What is a smart pointer and when should I use one?When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?How can I profile C++ code running on Linux?Why should I use a pointer rather than the object itself?Compiling an application for use in highly radioactive environmentsWhat are the new features in C++17?clang 3.9, auto_ptr and boostC++17 code not compiling on Travis with Clang-6.0C++17: explicit conversion function vs explicit constructor + implicit conversions - have the rules changed?C++17 - Binding rvalue reference to non-const lvalue ref
What does War Machine's "Canopy! Canopy!" line mean in "Avengers: Endgame"?
What does it mean by "d-ism of Leibniz" and "dotage of Newton" in simple English?
Scala list with same adjacent values
Are grass strips more dangerous than tarmac?
Is there an evolutionary advantage to having two heads?
How can I offer a test ride while selling a bike?
What is the most important characteristic of New Weird as a genre?
How did the Zip Chip and RocketChip accelerators work for the Apple II?
How do I get a list of only the files (not the directories) from a package?
Cryptography and patents
Does Peach's float negate shorthop knockback multipliers?
Pros and cons of writing a book review?
California: "For quality assurance, this phone call is being recorded"
What is the right way to float a home lab?
What is a natural deduction proof from ~(A↔B) to ~(A→B)?
Make a formula to get the highest score
Is it possible to kill all life on Earth?
Can you keep a readied action even through incapacitation?
Is there a rule that prohibits us from using 2 possessives in a row?
Explain Ant-Man's "not it" scene from Avengers: Endgame
Why does my electric oven present the option of 40A and 50A breakers?
How to properly maintain eye contact with people that have distinctive facial features?
How to write a vulnerable moment without it seeming cliche or mushy?
Looking after a wayward brother in mother's will
Should this code fail to compile in C++17?
What is a smart pointer and when should I use one?When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?How can I profile C++ code running on Linux?Why should I use a pointer rather than the object itself?Compiling an application for use in highly radioactive environmentsWhat are the new features in C++17?clang 3.9, auto_ptr and boostC++17 code not compiling on Travis with Clang-6.0C++17: explicit conversion function vs explicit constructor + implicit conversions - have the rules changed?C++17 - Binding rvalue reference to non-const lvalue ref
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I was updating a project to use C++17 and found a few instances where code that followed this pattern was causing a compile error on recent versions of clang:
#include <boost/variant.hpp>
struct vis : public boost::static_visitor<void>
void operator()(int) const
;
int main()
boost::variant<int> v = 0;
boost::apply_visitor(vis, v);
Using clang v8.0 in C++17 mode, this fails with the following error:
<source>:11:30: error: temporary of type 'boost::static_visitor<void>' has protected destructor
boost::apply_visitor(vis, v);
^
/opt/compiler-explorer/libs/boost_1_64_0/boost/variant/static_visitor.hpp:53:5: note: declared protected here
~static_visitor() = default;
However, it compiles cleanly in C++14 mode. I found that if I change the brace initialization vis
to parentheses vis()
, then it compiles correctly in both modes. Every version of gcc that I've tried allows both variants in C++17 mode.
Is this a correct change in behavior from C++14 to C++17, or is this a clang bug? If it is correct, why is it now invalid in C++17 (or maybe it always was, but clang just allows it in earlier standard revisions)?
c++ clang c++17 boost-variant
add a comment |
I was updating a project to use C++17 and found a few instances where code that followed this pattern was causing a compile error on recent versions of clang:
#include <boost/variant.hpp>
struct vis : public boost::static_visitor<void>
void operator()(int) const
;
int main()
boost::variant<int> v = 0;
boost::apply_visitor(vis, v);
Using clang v8.0 in C++17 mode, this fails with the following error:
<source>:11:30: error: temporary of type 'boost::static_visitor<void>' has protected destructor
boost::apply_visitor(vis, v);
^
/opt/compiler-explorer/libs/boost_1_64_0/boost/variant/static_visitor.hpp:53:5: note: declared protected here
~static_visitor() = default;
However, it compiles cleanly in C++14 mode. I found that if I change the brace initialization vis
to parentheses vis()
, then it compiles correctly in both modes. Every version of gcc that I've tried allows both variants in C++17 mode.
Is this a correct change in behavior from C++14 to C++17, or is this a clang bug? If it is correct, why is it now invalid in C++17 (or maybe it always was, but clang just allows it in earlier standard revisions)?
c++ clang c++17 boost-variant
It seem you use aggregate initialization instead of default constructor :-/ Changing tovis()
compiles.
– Jarod42
8 hours ago
1
Boost fixed this in 1.70. It's also discussed here.
– interjay
8 hours ago
add a comment |
I was updating a project to use C++17 and found a few instances where code that followed this pattern was causing a compile error on recent versions of clang:
#include <boost/variant.hpp>
struct vis : public boost::static_visitor<void>
void operator()(int) const
;
int main()
boost::variant<int> v = 0;
boost::apply_visitor(vis, v);
Using clang v8.0 in C++17 mode, this fails with the following error:
<source>:11:30: error: temporary of type 'boost::static_visitor<void>' has protected destructor
boost::apply_visitor(vis, v);
^
/opt/compiler-explorer/libs/boost_1_64_0/boost/variant/static_visitor.hpp:53:5: note: declared protected here
~static_visitor() = default;
However, it compiles cleanly in C++14 mode. I found that if I change the brace initialization vis
to parentheses vis()
, then it compiles correctly in both modes. Every version of gcc that I've tried allows both variants in C++17 mode.
Is this a correct change in behavior from C++14 to C++17, or is this a clang bug? If it is correct, why is it now invalid in C++17 (or maybe it always was, but clang just allows it in earlier standard revisions)?
c++ clang c++17 boost-variant
I was updating a project to use C++17 and found a few instances where code that followed this pattern was causing a compile error on recent versions of clang:
#include <boost/variant.hpp>
struct vis : public boost::static_visitor<void>
void operator()(int) const
;
int main()
boost::variant<int> v = 0;
boost::apply_visitor(vis, v);
Using clang v8.0 in C++17 mode, this fails with the following error:
<source>:11:30: error: temporary of type 'boost::static_visitor<void>' has protected destructor
boost::apply_visitor(vis, v);
^
/opt/compiler-explorer/libs/boost_1_64_0/boost/variant/static_visitor.hpp:53:5: note: declared protected here
~static_visitor() = default;
However, it compiles cleanly in C++14 mode. I found that if I change the brace initialization vis
to parentheses vis()
, then it compiles correctly in both modes. Every version of gcc that I've tried allows both variants in C++17 mode.
Is this a correct change in behavior from C++14 to C++17, or is this a clang bug? If it is correct, why is it now invalid in C++17 (or maybe it always was, but clang just allows it in earlier standard revisions)?
c++ clang c++17 boost-variant
c++ clang c++17 boost-variant
edited 8 hours ago
Barry
191k21345630
191k21345630
asked 8 hours ago
Jason RJason R
6,18223359
6,18223359
It seem you use aggregate initialization instead of default constructor :-/ Changing tovis()
compiles.
– Jarod42
8 hours ago
1
Boost fixed this in 1.70. It's also discussed here.
– interjay
8 hours ago
add a comment |
It seem you use aggregate initialization instead of default constructor :-/ Changing tovis()
compiles.
– Jarod42
8 hours ago
1
Boost fixed this in 1.70. It's also discussed here.
– interjay
8 hours ago
It seem you use aggregate initialization instead of default constructor :-/ Changing to
vis()
compiles.– Jarod42
8 hours ago
It seem you use aggregate initialization instead of default constructor :-/ Changing to
vis()
compiles.– Jarod42
8 hours ago
1
1
Boost fixed this in 1.70. It's also discussed here.
– interjay
8 hours ago
Boost fixed this in 1.70. It's also discussed here.
– interjay
8 hours ago
add a comment |
1 Answer
1
active
oldest
votes
clang is correct here. Here's a reduced example:
struct B
protected:
B()
;
struct D : B ;
auto d = D;
In C++14, D
is not an aggregate because it has a base class, so D
is "normal" (non-aggregate) initialization which invokes D
's default constructor, which in turn invokes B
's default constructor. This is fine, because D
has access to B
's default constructor.
In C++17, the definition of aggregate was widened - base classes are now allowed (as long as they're non-virtual
). D
is now an aggregate, which means that D
is aggregate initialization. And in aggregate-initialization, this means that we (the caller) are initializing all the subobjects - including the base class subobject. But we do not have access to B
's constructor (it is protected
), so we cannot invoke it, so it is ill-formed.
Fear not, the fix is easy. Use parentheses:
auto d = D();
This goes back to invoking D
's default constructor as before.
Perfect, that's what I was looking for: the widened definition of aggregate is the culprit.
– Jason R
8 hours ago
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%2f56367480%2fshould-this-code-fail-to-compile-in-c17%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
clang is correct here. Here's a reduced example:
struct B
protected:
B()
;
struct D : B ;
auto d = D;
In C++14, D
is not an aggregate because it has a base class, so D
is "normal" (non-aggregate) initialization which invokes D
's default constructor, which in turn invokes B
's default constructor. This is fine, because D
has access to B
's default constructor.
In C++17, the definition of aggregate was widened - base classes are now allowed (as long as they're non-virtual
). D
is now an aggregate, which means that D
is aggregate initialization. And in aggregate-initialization, this means that we (the caller) are initializing all the subobjects - including the base class subobject. But we do not have access to B
's constructor (it is protected
), so we cannot invoke it, so it is ill-formed.
Fear not, the fix is easy. Use parentheses:
auto d = D();
This goes back to invoking D
's default constructor as before.
Perfect, that's what I was looking for: the widened definition of aggregate is the culprit.
– Jason R
8 hours ago
add a comment |
clang is correct here. Here's a reduced example:
struct B
protected:
B()
;
struct D : B ;
auto d = D;
In C++14, D
is not an aggregate because it has a base class, so D
is "normal" (non-aggregate) initialization which invokes D
's default constructor, which in turn invokes B
's default constructor. This is fine, because D
has access to B
's default constructor.
In C++17, the definition of aggregate was widened - base classes are now allowed (as long as they're non-virtual
). D
is now an aggregate, which means that D
is aggregate initialization. And in aggregate-initialization, this means that we (the caller) are initializing all the subobjects - including the base class subobject. But we do not have access to B
's constructor (it is protected
), so we cannot invoke it, so it is ill-formed.
Fear not, the fix is easy. Use parentheses:
auto d = D();
This goes back to invoking D
's default constructor as before.
Perfect, that's what I was looking for: the widened definition of aggregate is the culprit.
– Jason R
8 hours ago
add a comment |
clang is correct here. Here's a reduced example:
struct B
protected:
B()
;
struct D : B ;
auto d = D;
In C++14, D
is not an aggregate because it has a base class, so D
is "normal" (non-aggregate) initialization which invokes D
's default constructor, which in turn invokes B
's default constructor. This is fine, because D
has access to B
's default constructor.
In C++17, the definition of aggregate was widened - base classes are now allowed (as long as they're non-virtual
). D
is now an aggregate, which means that D
is aggregate initialization. And in aggregate-initialization, this means that we (the caller) are initializing all the subobjects - including the base class subobject. But we do not have access to B
's constructor (it is protected
), so we cannot invoke it, so it is ill-formed.
Fear not, the fix is easy. Use parentheses:
auto d = D();
This goes back to invoking D
's default constructor as before.
clang is correct here. Here's a reduced example:
struct B
protected:
B()
;
struct D : B ;
auto d = D;
In C++14, D
is not an aggregate because it has a base class, so D
is "normal" (non-aggregate) initialization which invokes D
's default constructor, which in turn invokes B
's default constructor. This is fine, because D
has access to B
's default constructor.
In C++17, the definition of aggregate was widened - base classes are now allowed (as long as they're non-virtual
). D
is now an aggregate, which means that D
is aggregate initialization. And in aggregate-initialization, this means that we (the caller) are initializing all the subobjects - including the base class subobject. But we do not have access to B
's constructor (it is protected
), so we cannot invoke it, so it is ill-formed.
Fear not, the fix is easy. Use parentheses:
auto d = D();
This goes back to invoking D
's default constructor as before.
answered 8 hours ago
BarryBarry
191k21345630
191k21345630
Perfect, that's what I was looking for: the widened definition of aggregate is the culprit.
– Jason R
8 hours ago
add a comment |
Perfect, that's what I was looking for: the widened definition of aggregate is the culprit.
– Jason R
8 hours ago
Perfect, that's what I was looking for: the widened definition of aggregate is the culprit.
– Jason R
8 hours ago
Perfect, that's what I was looking for: the widened definition of aggregate is the culprit.
– Jason R
8 hours ago
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%2f56367480%2fshould-this-code-fail-to-compile-in-c17%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
It seem you use aggregate initialization instead of default constructor :-/ Changing to
vis()
compiles.– Jarod42
8 hours ago
1
Boost fixed this in 1.70. It's also discussed here.
– interjay
8 hours ago