I. Why is aware of this issue
Before using the C-style cast time, a more annoying place is due priority switching operation, resulting in the type of conversion out of a need to use additional brackets hold up, look very bloated. Later, I noticed seemingly higher priority in C ++ style cast operators, although the input has increased, but when the input is relatively smooth, and therefore looks more processes.
@ Harry tsecer: CAT -n cpp.style.cast.cpp
. 1 struct S
2 {
. 3 int X;
. 4};
. 5
. 6 int foo (void * VP)
. 7 {
. 8 return static_cast <const * S> (VP) -> X
. 9 + (S *) (VP) -> X;
10}
tsecer Harry @: G ++ -C cpp.style.cast.cpp
cpp.style.cast.cpp: the function 'int foo (void *)' in which:
cpp.style.cast.cpp: 9: 14: error: 'void *' is not a pointing object type
+ (S *) (VP) -> X;
^
tsecer @ Harry:
Two, cast priority
In the C language, clearly defines the priority of the cast ,
priority | Operators | description | Associativity |
---|---|---|---|
1 | :: |
Scope resolution | From left to right |
2 | a++ a-- |
Suffix increment and decrement | |
type() type{} |
Functional style transformation | ||
a() |
Function call | ||
a[] |
Subscript | ||
. -> |
Member Access | ||
3 | ++a --a |
Prefix increment and decrement | From right to left |
+a -a |
One yuan addition and subtraction | ||
! ~ |
Logic NOT and bitwise NOT | ||
(type) |
C-style transformation | ||
*a |
Indirect (dereference) | ||
&a |
Take site | ||
sizeof |
Take size [Note 1] | ||
co_await |
await expression (C ++ 20) | ||
new new[] |
Dynamic memory allocation | ||
delete delete[] |
Dynamic memory allocation |
Its priority and "prefix increment" (+) same, below the "Member access" (->) priority. But for C ++ style cast, that "notes" is the
table does not include const_cast, static_cast, dynamic_cast, reinterpret_cast, typeid, sizeof ..., noexcept and alignof, because they never have ambiguous.
But did not specify their priority. A post on Stack Overflow of the issues discussed .
Three, gcc processed in the syntax
You can see from the implementation of the function for C ++ style cast, as long as identify const_cast, static_cast, dynamic_cast, reinterpret_cast, keyword, behind the procedure is Yimapingchuan, then must be followed by a left angle bracket / less than sign (RT_LESS), type (typeid), the right angle bracket / greater than the number (RT_GREATER), a left parenthesis (RT_OPEN_PAREN), the expression (expression), there are brackets (RT_CLOSE_PAREN). The key is, after the completion of these analytic, direct calls build_dynamic_cast / build_static_cast / build_reinterpret_cast / build_const_cast to generate an expression, in this sense, C ++ style cast is more like an atomic operation, their entire grammatical structure constitutes a fundamental unit .
4.9.0-GCC \ GCC \ CP \ parser.c
/ * the Parse-A expression The postfix.
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( expression-list [opt] )
simple-type-specifier ( expression-list [opt] )
typename :: [opt] nested-name-specifier identifier
( expression-list [opt] )
typename :: [opt] nested-name-specifier template [opt] template-id
( expression-list [opt] )
postfix-expression . template [opt] id-expression
postfix-expression -> template [opt] id-expression
postfix-expression . pseudo-destructor-name
postfix-expression -> pseudo-destructor-name
postfix-expression ++
postfix-expression --
dynamic_cast < type-id > ( expression )
static_cast < type-id > ( expression )
reinterpret_cast < type-id > ( expression )
const_cast < type-id > ( expression )
typeid ( expression )
typeid ( type-id )
GNU Extension:
postfix-expression:
( type-id ) { initializer-list , [opt] }
This extension is a GNU version of the C99 compound-literal
construct. (The C99 grammar uses `type-name' instead of `type-id',
but they are essentially the same concept.)
If ADDRESS_P is true, the postfix expression is the operand of the
`&' operator. CAST_P is true if this expression is the target of a
cast.
If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are
class member access expressions [expr.ref].
Returns a representation of the expression. */
static tree
cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
bool member_access_only_p, bool decltype_p,
cp_id_kind * pidk_return)
{
cp_token *token;
location_t loc;
enum rid keyword;
cp_id_kind idk = CP_ID_KIND_NONE;
tree postfix_expression = NULL_TREE;
bool is_member_access = false;
int saved_in_statement = -1;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
loc = token->location;
/* Some of the productions are determined by keywords. */
keyword = token->keyword;
switch (keyword)
{
case RID_DYNCAST:
case RID_STATCAST:
case RID_REINTCAST:
case RID_CONSTCAST:
{
tree type;
tree expression;
const char *saved_message;
bool saved_in_type_id_in_expr_p;
/* All of these can be handled in the same way from the point
of view of parsing. Begin by consuming the token
identifying the cast. */
cp_lexer_consume_token (parser->lexer);
/* New types cannot be defined in the cast. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
= G_("types may not be defined in casts");
/* Look for the opening `<'. */
cp_parser_require (parser, CPP_LESS, RT_LESS);
/* Parse the type to which we are casting. */
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
parser->in_type_id_in_expr_p = true;
type = cp_parser_type_id (parser);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
/* Look for the closing `>'. */
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
/* Restore the old message. */
parser->type_definition_forbidden_message = saved_message;
bool saved_greater_than_is_operator_p
= parser->greater_than_is_operator_p;
parser->greater_than_is_operator_p = true;
/* And the expression which is being cast. */
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
expression = cp_parser_expression (parser, /*cast_p=*/true, & idk);
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
/* Only type conversions to integral or enumeration types
can be used in constant-expressions. */
if (!cast_valid_in_integral_constant_expression_p (type)
&& cp_parser_non_integral_constant_expression (parser, NIC_CAST))
return error_mark_node;
switch (keyword)
{
case RID_DYNCAST:
postfix_expression
= build_dynamic_cast (type, expression, tf_warning_or_error);
break;
case RID_STATCAST:
postfix_expression
= build_static_cast (type, expression, tf_warning_or_error);
break;
case RID_REINTCAST:
postfix_expression
= build_reinterpret_cast (type, expression,
tf_warning_or_error);
break;
case RID_CONSTCAST:
postfix_expression
= build_const_cast (type, expression, tf_warning_or_error);
break;
default:
gcc_unreachable ();
}
}
break;
……
}