Standard behavior for direct initialization of unsigned short
Clash Royale CLAN TAG#URR8PPP
up vote
16
down vote
favorite
I noticed today that in the example code:
void print(unsigned short a)
std::cout << a << std::endl;
Initialization and use works like this:
print(short (5));
But not like this:
print(unsigned short(6));
main.cpp:16:8: error: expected primary-expression before 'unsigned'
print(unsigned short(6));
And it's not to do with the type since this also works:
typedef unsigned short ushort;
print(ushort (6));
Live example.
So I went searching for what the standard says about value initialization. It turns out nothing:
The effects of value initialization are:
1) if T is a class type ...
2) if T is a non-union class type ...
2) if T is a class type ...
3) if T is an array type, ..
4) otherwise, the object is zero-initialized.
Modifications made for readability. Original source.
What are the rules about value initialization of POD types? What is the reason that unsigned
qualified types can't be value initialized? Is this more to do with the fact they are rvalues
?
c++ syntax casting initialization language-lawyer
add a comment |Â
up vote
16
down vote
favorite
I noticed today that in the example code:
void print(unsigned short a)
std::cout << a << std::endl;
Initialization and use works like this:
print(short (5));
But not like this:
print(unsigned short(6));
main.cpp:16:8: error: expected primary-expression before 'unsigned'
print(unsigned short(6));
And it's not to do with the type since this also works:
typedef unsigned short ushort;
print(ushort (6));
Live example.
So I went searching for what the standard says about value initialization. It turns out nothing:
The effects of value initialization are:
1) if T is a class type ...
2) if T is a non-union class type ...
2) if T is a class type ...
3) if T is an array type, ..
4) otherwise, the object is zero-initialized.
Modifications made for readability. Original source.
What are the rules about value initialization of POD types? What is the reason that unsigned
qualified types can't be value initialized? Is this more to do with the fact they are rvalues
?
c++ syntax casting initialization language-lawyer
add a comment |Â
up vote
16
down vote
favorite
up vote
16
down vote
favorite
I noticed today that in the example code:
void print(unsigned short a)
std::cout << a << std::endl;
Initialization and use works like this:
print(short (5));
But not like this:
print(unsigned short(6));
main.cpp:16:8: error: expected primary-expression before 'unsigned'
print(unsigned short(6));
And it's not to do with the type since this also works:
typedef unsigned short ushort;
print(ushort (6));
Live example.
So I went searching for what the standard says about value initialization. It turns out nothing:
The effects of value initialization are:
1) if T is a class type ...
2) if T is a non-union class type ...
2) if T is a class type ...
3) if T is an array type, ..
4) otherwise, the object is zero-initialized.
Modifications made for readability. Original source.
What are the rules about value initialization of POD types? What is the reason that unsigned
qualified types can't be value initialized? Is this more to do with the fact they are rvalues
?
c++ syntax casting initialization language-lawyer
I noticed today that in the example code:
void print(unsigned short a)
std::cout << a << std::endl;
Initialization and use works like this:
print(short (5));
But not like this:
print(unsigned short(6));
main.cpp:16:8: error: expected primary-expression before 'unsigned'
print(unsigned short(6));
And it's not to do with the type since this also works:
typedef unsigned short ushort;
print(ushort (6));
Live example.
So I went searching for what the standard says about value initialization. It turns out nothing:
The effects of value initialization are:
1) if T is a class type ...
2) if T is a non-union class type ...
2) if T is a class type ...
3) if T is an array type, ..
4) otherwise, the object is zero-initialized.
Modifications made for readability. Original source.
What are the rules about value initialization of POD types? What is the reason that unsigned
qualified types can't be value initialized? Is this more to do with the fact they are rvalues
?
c++ syntax casting initialization language-lawyer
c++ syntax casting initialization language-lawyer
edited Sep 10 at 10:53
songyuanyao
85k9163222
85k9163222
asked Aug 17 at 10:58
Fantastic Mr Fox
17.4k1765125
17.4k1765125
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
21
down vote
accepted
What is the reason that
unsigned
qualified types can't be value initialized?
It's just because only single-word type name could be used in functional cast expression, while unsigned short
is not a single-word type name; short
is.
The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name:
unsigned int(expression)
orint*(expression)
are not valid), followed by a single expression in parentheses.
As you showed, you can use typedef
as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6)
, or (unsigned short)6
.
From the standard, ç7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:
A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.
And simple-type-specifier:
simple-type-specifier:
nested-name-specifier opt
type-name
nested-name-specifier template simple-template-id
nested-name-specifier opt
template-name
char
char16_t
char32_t
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
auto
decltype-specifier
type-name:
class-name
enum-name
typedef-name
simple-template-id
decltype-specifier:
decltype ( expression )
decltype ( auto )
typename-specifier:
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier template opt
simple-template-id
Ahh, ok, its not even value initialization. Makes sense. Good answer.
â Fantastic Mr Fox
Aug 17 at 11:06
A Follow up question which is heavily related is why in value initialization does not coverother types
. In this expressionunsigned int i(6)
is it value initialized, or zero initialized?
â Fantastic Mr Fox
Aug 17 at 11:10
1
Note that(unsigned short)()
, i.e., trying to use value initialisation does not work.(unsigned short)
does work, though.
â Dietmar Kühl
Aug 17 at 11:12
2
@FantasticMrFoxunsigned int i(6)
is direct initialization.i
is initialized to6
.
â songyuanyao
Aug 17 at 11:12
@songyuanyao I obviously have some work to do learning initialization names.
â Fantastic Mr Fox
Aug 17 at 11:15
 |Â
show 3 more comments
up vote
7
down vote
That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work
template <typename T> void use(T);
int main()
use(unsigned int());
use(const int());
use(long long());
The work-around is to use an alias for the respective type instead, i.e., all of these do work:
template <typename T> void use(T);
int main()
using type = unsigned int; use(type());
using type = const int; use(type());
using type = long long; use(type());
Parenthesis can also be used for value initialisation although the require the use of curlies:
template <typename T> void use(T);
int main()
use((unsigned int));
use((const int));
use((long long));
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
21
down vote
accepted
What is the reason that
unsigned
qualified types can't be value initialized?
It's just because only single-word type name could be used in functional cast expression, while unsigned short
is not a single-word type name; short
is.
The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name:
unsigned int(expression)
orint*(expression)
are not valid), followed by a single expression in parentheses.
As you showed, you can use typedef
as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6)
, or (unsigned short)6
.
From the standard, ç7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:
A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.
And simple-type-specifier:
simple-type-specifier:
nested-name-specifier opt
type-name
nested-name-specifier template simple-template-id
nested-name-specifier opt
template-name
char
char16_t
char32_t
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
auto
decltype-specifier
type-name:
class-name
enum-name
typedef-name
simple-template-id
decltype-specifier:
decltype ( expression )
decltype ( auto )
typename-specifier:
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier template opt
simple-template-id
Ahh, ok, its not even value initialization. Makes sense. Good answer.
â Fantastic Mr Fox
Aug 17 at 11:06
A Follow up question which is heavily related is why in value initialization does not coverother types
. In this expressionunsigned int i(6)
is it value initialized, or zero initialized?
â Fantastic Mr Fox
Aug 17 at 11:10
1
Note that(unsigned short)()
, i.e., trying to use value initialisation does not work.(unsigned short)
does work, though.
â Dietmar Kühl
Aug 17 at 11:12
2
@FantasticMrFoxunsigned int i(6)
is direct initialization.i
is initialized to6
.
â songyuanyao
Aug 17 at 11:12
@songyuanyao I obviously have some work to do learning initialization names.
â Fantastic Mr Fox
Aug 17 at 11:15
 |Â
show 3 more comments
up vote
21
down vote
accepted
What is the reason that
unsigned
qualified types can't be value initialized?
It's just because only single-word type name could be used in functional cast expression, while unsigned short
is not a single-word type name; short
is.
The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name:
unsigned int(expression)
orint*(expression)
are not valid), followed by a single expression in parentheses.
As you showed, you can use typedef
as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6)
, or (unsigned short)6
.
From the standard, ç7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:
A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.
And simple-type-specifier:
simple-type-specifier:
nested-name-specifier opt
type-name
nested-name-specifier template simple-template-id
nested-name-specifier opt
template-name
char
char16_t
char32_t
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
auto
decltype-specifier
type-name:
class-name
enum-name
typedef-name
simple-template-id
decltype-specifier:
decltype ( expression )
decltype ( auto )
typename-specifier:
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier template opt
simple-template-id
Ahh, ok, its not even value initialization. Makes sense. Good answer.
â Fantastic Mr Fox
Aug 17 at 11:06
A Follow up question which is heavily related is why in value initialization does not coverother types
. In this expressionunsigned int i(6)
is it value initialized, or zero initialized?
â Fantastic Mr Fox
Aug 17 at 11:10
1
Note that(unsigned short)()
, i.e., trying to use value initialisation does not work.(unsigned short)
does work, though.
â Dietmar Kühl
Aug 17 at 11:12
2
@FantasticMrFoxunsigned int i(6)
is direct initialization.i
is initialized to6
.
â songyuanyao
Aug 17 at 11:12
@songyuanyao I obviously have some work to do learning initialization names.
â Fantastic Mr Fox
Aug 17 at 11:15
 |Â
show 3 more comments
up vote
21
down vote
accepted
up vote
21
down vote
accepted
What is the reason that
unsigned
qualified types can't be value initialized?
It's just because only single-word type name could be used in functional cast expression, while unsigned short
is not a single-word type name; short
is.
The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name:
unsigned int(expression)
orint*(expression)
are not valid), followed by a single expression in parentheses.
As you showed, you can use typedef
as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6)
, or (unsigned short)6
.
From the standard, ç7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:
A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.
And simple-type-specifier:
simple-type-specifier:
nested-name-specifier opt
type-name
nested-name-specifier template simple-template-id
nested-name-specifier opt
template-name
char
char16_t
char32_t
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
auto
decltype-specifier
type-name:
class-name
enum-name
typedef-name
simple-template-id
decltype-specifier:
decltype ( expression )
decltype ( auto )
typename-specifier:
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier template opt
simple-template-id
What is the reason that
unsigned
qualified types can't be value initialized?
It's just because only single-word type name could be used in functional cast expression, while unsigned short
is not a single-word type name; short
is.
The functional cast expression consists of a simple type specifier or a typedef specifier (in other words, a single-word type name:
unsigned int(expression)
orint*(expression)
are not valid), followed by a single expression in parentheses.
As you showed, you can use typedef
as the workaround, or add parentheses to change it to c-style cast expression, e.g. (unsigned short)(6)
, or (unsigned short)6
.
From the standard, ç7.6.1.3/1 Explicit type conversion (functional notation) [expr.type.conv]:
A simple-type-specifier or typename-specifier followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer.
And simple-type-specifier:
simple-type-specifier:
nested-name-specifier opt
type-name
nested-name-specifier template simple-template-id
nested-name-specifier opt
template-name
char
char16_t
char32_t
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
auto
decltype-specifier
type-name:
class-name
enum-name
typedef-name
simple-template-id
decltype-specifier:
decltype ( expression )
decltype ( auto )
typename-specifier:
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier template opt
simple-template-id
edited Aug 17 at 11:32
answered Aug 17 at 11:04
songyuanyao
85k9163222
85k9163222
Ahh, ok, its not even value initialization. Makes sense. Good answer.
â Fantastic Mr Fox
Aug 17 at 11:06
A Follow up question which is heavily related is why in value initialization does not coverother types
. In this expressionunsigned int i(6)
is it value initialized, or zero initialized?
â Fantastic Mr Fox
Aug 17 at 11:10
1
Note that(unsigned short)()
, i.e., trying to use value initialisation does not work.(unsigned short)
does work, though.
â Dietmar Kühl
Aug 17 at 11:12
2
@FantasticMrFoxunsigned int i(6)
is direct initialization.i
is initialized to6
.
â songyuanyao
Aug 17 at 11:12
@songyuanyao I obviously have some work to do learning initialization names.
â Fantastic Mr Fox
Aug 17 at 11:15
 |Â
show 3 more comments
Ahh, ok, its not even value initialization. Makes sense. Good answer.
â Fantastic Mr Fox
Aug 17 at 11:06
A Follow up question which is heavily related is why in value initialization does not coverother types
. In this expressionunsigned int i(6)
is it value initialized, or zero initialized?
â Fantastic Mr Fox
Aug 17 at 11:10
1
Note that(unsigned short)()
, i.e., trying to use value initialisation does not work.(unsigned short)
does work, though.
â Dietmar Kühl
Aug 17 at 11:12
2
@FantasticMrFoxunsigned int i(6)
is direct initialization.i
is initialized to6
.
â songyuanyao
Aug 17 at 11:12
@songyuanyao I obviously have some work to do learning initialization names.
â Fantastic Mr Fox
Aug 17 at 11:15
Ahh, ok, its not even value initialization. Makes sense. Good answer.
â Fantastic Mr Fox
Aug 17 at 11:06
Ahh, ok, its not even value initialization. Makes sense. Good answer.
â Fantastic Mr Fox
Aug 17 at 11:06
A Follow up question which is heavily related is why in value initialization does not cover
other types
. In this expression unsigned int i(6)
is it value initialized, or zero initialized?â Fantastic Mr Fox
Aug 17 at 11:10
A Follow up question which is heavily related is why in value initialization does not cover
other types
. In this expression unsigned int i(6)
is it value initialized, or zero initialized?â Fantastic Mr Fox
Aug 17 at 11:10
1
1
Note that
(unsigned short)()
, i.e., trying to use value initialisation does not work. (unsigned short)
does work, though.â Dietmar Kühl
Aug 17 at 11:12
Note that
(unsigned short)()
, i.e., trying to use value initialisation does not work. (unsigned short)
does work, though.â Dietmar Kühl
Aug 17 at 11:12
2
2
@FantasticMrFox
unsigned int i(6)
is direct initialization. i
is initialized to 6
.â songyuanyao
Aug 17 at 11:12
@FantasticMrFox
unsigned int i(6)
is direct initialization. i
is initialized to 6
.â songyuanyao
Aug 17 at 11:12
@songyuanyao I obviously have some work to do learning initialization names.
â Fantastic Mr Fox
Aug 17 at 11:15
@songyuanyao I obviously have some work to do learning initialization names.
â Fantastic Mr Fox
Aug 17 at 11:15
 |Â
show 3 more comments
up vote
7
down vote
That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work
template <typename T> void use(T);
int main()
use(unsigned int());
use(const int());
use(long long());
The work-around is to use an alias for the respective type instead, i.e., all of these do work:
template <typename T> void use(T);
int main()
using type = unsigned int; use(type());
using type = const int; use(type());
using type = long long; use(type());
Parenthesis can also be used for value initialisation although the require the use of curlies:
template <typename T> void use(T);
int main()
use((unsigned int));
use((const int));
use((long long));
add a comment |Â
up vote
7
down vote
That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work
template <typename T> void use(T);
int main()
use(unsigned int());
use(const int());
use(long long());
The work-around is to use an alias for the respective type instead, i.e., all of these do work:
template <typename T> void use(T);
int main()
using type = unsigned int; use(type());
using type = const int; use(type());
using type = long long; use(type());
Parenthesis can also be used for value initialisation although the require the use of curlies:
template <typename T> void use(T);
int main()
use((unsigned int));
use((const int));
use((long long));
add a comment |Â
up vote
7
down vote
up vote
7
down vote
That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work
template <typename T> void use(T);
int main()
use(unsigned int());
use(const int());
use(long long());
The work-around is to use an alias for the respective type instead, i.e., all of these do work:
template <typename T> void use(T);
int main()
using type = unsigned int; use(type());
using type = const int; use(type());
using type = long long; use(type());
Parenthesis can also be used for value initialisation although the require the use of curlies:
template <typename T> void use(T);
int main()
use((unsigned int));
use((const int));
use((long long));
That's just a glitch in the grammar: the two word type names don't work when creating temporary objects. That is, none of these work
template <typename T> void use(T);
int main()
use(unsigned int());
use(const int());
use(long long());
The work-around is to use an alias for the respective type instead, i.e., all of these do work:
template <typename T> void use(T);
int main()
using type = unsigned int; use(type());
using type = const int; use(type());
using type = long long; use(type());
Parenthesis can also be used for value initialisation although the require the use of curlies:
template <typename T> void use(T);
int main()
use((unsigned int));
use((const int));
use((long long));
edited Aug 17 at 11:14
answered Aug 17 at 11:09
Dietmar Kühl
123k7146306
123k7146306
add a comment |Â
add a comment |Â
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
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51893895%2fstandard-behavior-for-direct-initialization-of-unsigned-short%23new-answer', 'question_page');
);
Post as a guest
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
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
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