Why doesn't “auto ch = unsigned char{'p'}” compile under C++ 17?












22















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.










share|improve this question























  • @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 char as 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
















22















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.










share|improve this question























  • @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 char as 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














22












22








22


2






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.










share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 9 hours ago









Violet GiraffeViolet Giraffe

14.7k28135249




14.7k28135249













  • @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 char as 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








  • 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 char as 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












1 Answer
1






active

oldest

votes


















31














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





share|improve this answer





















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





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











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


}
});














draft saved

draft discarded


















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









31














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





share|improve this answer





















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





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
















31














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





share|improve this answer





















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





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














31












31








31







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





share|improve this answer















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






share|improve this answer














share|improve this answer



share|improve this answer








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





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














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





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








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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Paul Cézanne

UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

Angular material date-picker (MatDatepicker) auto completes the date on focus out