Why doesn't “auto ch = unsigned char{'p'}” compile under C++ 17?
I'm puzzled. Isn't const auto ch = unsigned char{'p'}; a perfectly valid initialization expression? Fails to be compiled by all three major compilers with almost identical error messages:
error: expected '(' for function-style cast or type construction
Swapping curly braces for ('p') changes nothing.
It does, however, compile without the signed or unsigned keyword.
Online demo.
c++ c++14 c++17
add a comment |
I'm puzzled. Isn't const auto ch = unsigned char{'p'}; a perfectly valid initialization expression? Fails to be compiled by all three major compilers with almost identical error messages:
error: expected '(' for function-style cast or type construction
Swapping curly braces for ('p') changes nothing.
It does, however, compile without the signed or unsigned keyword.
Online demo.
c++ c++14 c++17
@FrançoisAndrieux: so doesconst auto ch = static_cast<unsigned char>('p'), but that's conversion, not initialization.
– Violet Giraffe
9 hours ago
3
using T = unsigned char; const auto ch = T{'p'};seems to work.
– François Andrieux
9 hours ago
@FrançoisAndrieux: Hm, do you think the compiler simply fails to parseunsigned charas a single type name in this context?
– Violet Giraffe
9 hours ago
1
const auto ch = (unsigned char){'p'};?
– Yakk - Adam Nevraumont
6 hours ago
add a comment |
I'm puzzled. Isn't const auto ch = unsigned char{'p'}; a perfectly valid initialization expression? Fails to be compiled by all three major compilers with almost identical error messages:
error: expected '(' for function-style cast or type construction
Swapping curly braces for ('p') changes nothing.
It does, however, compile without the signed or unsigned keyword.
Online demo.
c++ c++14 c++17
I'm puzzled. Isn't const auto ch = unsigned char{'p'}; a perfectly valid initialization expression? Fails to be compiled by all three major compilers with almost identical error messages:
error: expected '(' for function-style cast or type construction
Swapping curly braces for ('p') changes nothing.
It does, however, compile without the signed or unsigned keyword.
Online demo.
c++ c++14 c++17
c++ c++14 c++17
asked 9 hours ago
Violet GiraffeViolet Giraffe
14.7k28135249
14.7k28135249
@FrançoisAndrieux: so doesconst auto ch = static_cast<unsigned char>('p'), but that's conversion, not initialization.
– Violet Giraffe
9 hours ago
3
using T = unsigned char; const auto ch = T{'p'};seems to work.
– François Andrieux
9 hours ago
@FrançoisAndrieux: Hm, do you think the compiler simply fails to parseunsigned charas a single type name in this context?
– Violet Giraffe
9 hours ago
1
const auto ch = (unsigned char){'p'};?
– Yakk - Adam Nevraumont
6 hours ago
add a comment |
@FrançoisAndrieux: so doesconst auto ch = static_cast<unsigned char>('p'), but that's conversion, not initialization.
– Violet Giraffe
9 hours ago
3
using T = unsigned char; const auto ch = T{'p'};seems to work.
– François Andrieux
9 hours ago
@FrançoisAndrieux: Hm, do you think the compiler simply fails to parseunsigned charas a single type name in this context?
– Violet Giraffe
9 hours ago
1
const auto ch = (unsigned char){'p'};?
– Yakk - Adam Nevraumont
6 hours ago
@FrançoisAndrieux: so does
const auto ch = static_cast<unsigned char>('p'), but that's conversion, not initialization.– Violet Giraffe
9 hours ago
@FrançoisAndrieux: so does
const auto ch = static_cast<unsigned char>('p'), but that's conversion, not initialization.– Violet Giraffe
9 hours ago
3
3
using T = unsigned char; const auto ch = T{'p'}; seems to work.– François Andrieux
9 hours ago
using T = unsigned char; const auto ch = T{'p'}; seems to work.– François Andrieux
9 hours ago
@FrançoisAndrieux: Hm, do you think the compiler simply fails to parse
unsigned char as a single type name in this context?– Violet Giraffe
9 hours ago
@FrançoisAndrieux: Hm, do you think the compiler simply fails to parse
unsigned char as a single type name in this context?– Violet Giraffe
9 hours ago
1
1
const auto ch = (unsigned char){'p'};?– Yakk - Adam Nevraumont
6 hours ago
const auto ch = (unsigned char){'p'};?– Yakk - Adam Nevraumont
6 hours ago
add a comment |
1 Answer
1
active
oldest
votes
Because only single-word type name could be used for this kind of explicit type conversion.
A single-word type name followed by a braced-init-list is a prvalue of the specified type
designating a temporary (until C++17)whose result object is (since C++17)direct-list-initialized with the specified braced-init-list.
unsigned char is not a single-word type name, while char is. And this is true for functional cast expression too, that's why ('p') doesn't work either.
As the workaround, you can
using uc = unsigned char; // or use typedef
const auto ch = uc{'p'};
Or change it to other cast styles.
const auto ch = (unsigned char) 'p'; // c-style cast expression
const auto ch = static_cast<unsigned char>('p'); // static_cast conversion
5
Do you happen to know the reason for this limitation? Like, if multi-word type names were allowed here, what other things would become broken?
– Violet Giraffe
9 hours ago
1
@VioletGiraffe To be honest I don't know; I only know that the standard says so.
– songyuanyao
9 hours ago
1
@VioletGiraffe Becauseuc{'p'}/uc('p')is a functional cast. A function name can't have a space in it so neither can the type name.
– NathanOliver
8 hours ago
1
@curiousguy For all intents and purposes it is. If the type is a class type then the constructor is called. the cast and call have the exact same syntax and grammar.
– NathanOliver
8 hours ago
4
C-style cast, really? How aboutstatic_castinstead (or in case Boost is used,boost::implicit_cast)? The language allows a simple-type-specifier or (in a template) a typename-specifier, BTW, in a function-style cast, to be precise. Your statement that it "can't have a space" is slightly misleading because e.g.std :: uint8_thas spaces and is a valid simple-type-specifier.
– Arne Vogel
8 hours ago
|
show 2 more comments
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%2f54947170%2fwhy-doesnt-auto-ch-unsigned-charp-compile-under-c-17%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
Because only single-word type name could be used for this kind of explicit type conversion.
A single-word type name followed by a braced-init-list is a prvalue of the specified type
designating a temporary (until C++17)whose result object is (since C++17)direct-list-initialized with the specified braced-init-list.
unsigned char is not a single-word type name, while char is. And this is true for functional cast expression too, that's why ('p') doesn't work either.
As the workaround, you can
using uc = unsigned char; // or use typedef
const auto ch = uc{'p'};
Or change it to other cast styles.
const auto ch = (unsigned char) 'p'; // c-style cast expression
const auto ch = static_cast<unsigned char>('p'); // static_cast conversion
5
Do you happen to know the reason for this limitation? Like, if multi-word type names were allowed here, what other things would become broken?
– Violet Giraffe
9 hours ago
1
@VioletGiraffe To be honest I don't know; I only know that the standard says so.
– songyuanyao
9 hours ago
1
@VioletGiraffe Becauseuc{'p'}/uc('p')is a functional cast. A function name can't have a space in it so neither can the type name.
– NathanOliver
8 hours ago
1
@curiousguy For all intents and purposes it is. If the type is a class type then the constructor is called. the cast and call have the exact same syntax and grammar.
– NathanOliver
8 hours ago
4
C-style cast, really? How aboutstatic_castinstead (or in case Boost is used,boost::implicit_cast)? The language allows a simple-type-specifier or (in a template) a typename-specifier, BTW, in a function-style cast, to be precise. Your statement that it "can't have a space" is slightly misleading because e.g.std :: uint8_thas spaces and is a valid simple-type-specifier.
– Arne Vogel
8 hours ago
|
show 2 more comments
Because only single-word type name could be used for this kind of explicit type conversion.
A single-word type name followed by a braced-init-list is a prvalue of the specified type
designating a temporary (until C++17)whose result object is (since C++17)direct-list-initialized with the specified braced-init-list.
unsigned char is not a single-word type name, while char is. And this is true for functional cast expression too, that's why ('p') doesn't work either.
As the workaround, you can
using uc = unsigned char; // or use typedef
const auto ch = uc{'p'};
Or change it to other cast styles.
const auto ch = (unsigned char) 'p'; // c-style cast expression
const auto ch = static_cast<unsigned char>('p'); // static_cast conversion
5
Do you happen to know the reason for this limitation? Like, if multi-word type names were allowed here, what other things would become broken?
– Violet Giraffe
9 hours ago
1
@VioletGiraffe To be honest I don't know; I only know that the standard says so.
– songyuanyao
9 hours ago
1
@VioletGiraffe Becauseuc{'p'}/uc('p')is a functional cast. A function name can't have a space in it so neither can the type name.
– NathanOliver
8 hours ago
1
@curiousguy For all intents and purposes it is. If the type is a class type then the constructor is called. the cast and call have the exact same syntax and grammar.
– NathanOliver
8 hours ago
4
C-style cast, really? How aboutstatic_castinstead (or in case Boost is used,boost::implicit_cast)? The language allows a simple-type-specifier or (in a template) a typename-specifier, BTW, in a function-style cast, to be precise. Your statement that it "can't have a space" is slightly misleading because e.g.std :: uint8_thas spaces and is a valid simple-type-specifier.
– Arne Vogel
8 hours ago
|
show 2 more comments
Because only single-word type name could be used for this kind of explicit type conversion.
A single-word type name followed by a braced-init-list is a prvalue of the specified type
designating a temporary (until C++17)whose result object is (since C++17)direct-list-initialized with the specified braced-init-list.
unsigned char is not a single-word type name, while char is. And this is true for functional cast expression too, that's why ('p') doesn't work either.
As the workaround, you can
using uc = unsigned char; // or use typedef
const auto ch = uc{'p'};
Or change it to other cast styles.
const auto ch = (unsigned char) 'p'; // c-style cast expression
const auto ch = static_cast<unsigned char>('p'); // static_cast conversion
Because only single-word type name could be used for this kind of explicit type conversion.
A single-word type name followed by a braced-init-list is a prvalue of the specified type
designating a temporary (until C++17)whose result object is (since C++17)direct-list-initialized with the specified braced-init-list.
unsigned char is not a single-word type name, while char is. And this is true for functional cast expression too, that's why ('p') doesn't work either.
As the workaround, you can
using uc = unsigned char; // or use typedef
const auto ch = uc{'p'};
Or change it to other cast styles.
const auto ch = (unsigned char) 'p'; // c-style cast expression
const auto ch = static_cast<unsigned char>('p'); // static_cast conversion
edited 8 hours ago
answered 9 hours ago
songyuanyaosongyuanyao
92.2k11177242
92.2k11177242
5
Do you happen to know the reason for this limitation? Like, if multi-word type names were allowed here, what other things would become broken?
– Violet Giraffe
9 hours ago
1
@VioletGiraffe To be honest I don't know; I only know that the standard says so.
– songyuanyao
9 hours ago
1
@VioletGiraffe Becauseuc{'p'}/uc('p')is a functional cast. A function name can't have a space in it so neither can the type name.
– NathanOliver
8 hours ago
1
@curiousguy For all intents and purposes it is. If the type is a class type then the constructor is called. the cast and call have the exact same syntax and grammar.
– NathanOliver
8 hours ago
4
C-style cast, really? How aboutstatic_castinstead (or in case Boost is used,boost::implicit_cast)? The language allows a simple-type-specifier or (in a template) a typename-specifier, BTW, in a function-style cast, to be precise. Your statement that it "can't have a space" is slightly misleading because e.g.std :: uint8_thas spaces and is a valid simple-type-specifier.
– Arne Vogel
8 hours ago
|
show 2 more comments
5
Do you happen to know the reason for this limitation? Like, if multi-word type names were allowed here, what other things would become broken?
– Violet Giraffe
9 hours ago
1
@VioletGiraffe To be honest I don't know; I only know that the standard says so.
– songyuanyao
9 hours ago
1
@VioletGiraffe Becauseuc{'p'}/uc('p')is a functional cast. A function name can't have a space in it so neither can the type name.
– NathanOliver
8 hours ago
1
@curiousguy For all intents and purposes it is. If the type is a class type then the constructor is called. the cast and call have the exact same syntax and grammar.
– NathanOliver
8 hours ago
4
C-style cast, really? How aboutstatic_castinstead (or in case Boost is used,boost::implicit_cast)? The language allows a simple-type-specifier or (in a template) a typename-specifier, BTW, in a function-style cast, to be precise. Your statement that it "can't have a space" is slightly misleading because e.g.std :: uint8_thas spaces and is a valid simple-type-specifier.
– Arne Vogel
8 hours ago
5
5
Do you happen to know the reason for this limitation? Like, if multi-word type names were allowed here, what other things would become broken?
– Violet Giraffe
9 hours ago
Do you happen to know the reason for this limitation? Like, if multi-word type names were allowed here, what other things would become broken?
– Violet Giraffe
9 hours ago
1
1
@VioletGiraffe To be honest I don't know; I only know that the standard says so.
– songyuanyao
9 hours ago
@VioletGiraffe To be honest I don't know; I only know that the standard says so.
– songyuanyao
9 hours ago
1
1
@VioletGiraffe Because
uc{'p'}/uc('p') is a functional cast. A function name can't have a space in it so neither can the type name.– NathanOliver
8 hours ago
@VioletGiraffe Because
uc{'p'}/uc('p') is a functional cast. A function name can't have a space in it so neither can the type name.– NathanOliver
8 hours ago
1
1
@curiousguy For all intents and purposes it is. If the type is a class type then the constructor is called. the cast and call have the exact same syntax and grammar.
– NathanOliver
8 hours ago
@curiousguy For all intents and purposes it is. If the type is a class type then the constructor is called. the cast and call have the exact same syntax and grammar.
– NathanOliver
8 hours ago
4
4
C-style cast, really? How about
static_cast instead (or in case Boost is used, boost::implicit_cast)? The language allows a simple-type-specifier or (in a template) a typename-specifier, BTW, in a function-style cast, to be precise. Your statement that it "can't have a space" is slightly misleading because e.g. std :: uint8_t has spaces and is a valid simple-type-specifier.– Arne Vogel
8 hours ago
C-style cast, really? How about
static_cast instead (or in case Boost is used, boost::implicit_cast)? The language allows a simple-type-specifier or (in a template) a typename-specifier, BTW, in a function-style cast, to be precise. Your statement that it "can't have a space" is slightly misleading because e.g. std :: uint8_t has spaces and is a valid simple-type-specifier.– Arne Vogel
8 hours ago
|
show 2 more comments
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%2f54947170%2fwhy-doesnt-auto-ch-unsigned-charp-compile-under-c-17%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
@FrançoisAndrieux: so does
const auto ch = static_cast<unsigned char>('p'), but that's conversion, not initialization.– Violet Giraffe
9 hours ago
3
using T = unsigned char; const auto ch = T{'p'};seems to work.– François Andrieux
9 hours ago
@FrançoisAndrieux: Hm, do you think the compiler simply fails to parse
unsigned charas a single type name in this context?– Violet Giraffe
9 hours ago
1
const auto ch = (unsigned char){'p'};?– Yakk - Adam Nevraumont
6 hours ago