I read technical documentation for some projects which are created with C++. I found a line of code that contains syntax I don't understand:
using c = char (& (cClass::* [1]) (cClass(*)[2]) &)[3];
I see the using
keyword here. That means we deal with an alias, but what does this line do? How can I understand it? I think this creates a named alias c
and assigns the result of the expression on the right to it. But what is in this expression?
Syntax errors: Errors that occur when you violate the rules of writing C/C++ syntax are known as syntax errors. This compiler error indicates something that must be fixed before the code can be compiled. All these errors are detected by compiler and thus are known as compile-time errors.
The syntax of the C programming language is the set of rules governing writing of software in the C language. It is designed to allow for programs that are extremely terse, have a close relationship with the resulting object code, and yet provide relatively high-level data abstraction.
The most commonly occurring syntax errors in C language are: Missing semi-colon (;) Missing parenthesis ({}) Assigning value to a variable without declaring it.
Here's how your type is read, step by step. For the sake of clarity, below we declare a variable x
.
T x[1]
x
is an array (length 1) of type T
cClass::* x[1]
x
is an array (length 1) of pointer-to-member inside cClass
.
V (cClass::* x[1]) (U)
x
is an array (length 1) of pointer-to-member-function inside cClass
. Said member function takes U
as argument and returns V
.
V (cClass::* x[1]) (U) &
x
is an array (length 1) of pointer-to-member-function inside cClass
. Said member function takes U
as argument and returns V
, and can only be called on lvalues.
V & (cClass::* x[1]) (U) &
x
is an array (length 1) of pointer-to-member-function inside cClass
. Said member function takes U
as argument and returns reference-to-V
, and can only be called on lvalues.
V (& (cClass::* x[1]) (U) &)[3]
x
is an array (length 1) of pointer-to-member-function inside cClass
. Said member function takes U
as argument and returns a reference to array (length 3) of V
, and can only be called on lvalues.
Finally, to get your actual type
char (& (cClass::* x[1]) (cClass(*)[2]) &)[3]
we choose V = char
, and U = (cClass(*)[2])
, the latter being a pointer to array (length 2) of cClass
.
More readable alternative:
using char3 = char [3]; using ptrTo2cClass = cClass(*)[2]; using ptrToMethod = char3 & (cClass::*) (ptrTo2cClass) &; using c = ptrToMethod[1];
Types have to be interpreted starting from the middle (where a variable name would be, if it was a variable declaration). You go the right, until you hit the end or )
. Then you go to the left, until you hit the beginning or (
. At this point you either interpreted the whole type (then you're done), or you're inside of (...)
, in which case you discard them and repeat the same procedure (go to the right, then to the left).
Since this is not a variable declaration, you first need to find where the variable name would be if it was one. It's easier to do intuitively (once you get some experience), but a decent rule of thumb is to go from the left until you hit either )
, or (...)
, or [...]
.
Knowing this, we can turn this into a variable declaration. I've added x
as the variable name:
char (& (cClass::*x[1]) (cClass(*)[2]) &)[3];
Now we can start reading the type. First we go to the right: x
Variable x
is... x[1]
an array with 1 element, containing...
(Nothing else to the right, go to the left.) cClass::*x[1]
a pointer to member of class cClass
, of type... (cClass::*x[1])
(Nothing else to the left, skip parentheses.) (cClass::*x[1]) (............) &
a function with some parameters, &
-qualified1, returning...
(Nothing else to the right, go to the left.) & (cClass::*x[1]) (............) &
a reference to... (& (cClass::*x[1]) (............) &)
(Nothing else to the left, skip parentheses.) (& (cClass::*x[1]) (............) &)[3]
an array with 3 elements, containing...char (& (cClass::*x[1]) (............) &)[3]
char
s
And we're finished. The type of the function parameter (cClass(*)[2]
) has to be interpreted separately, using the same procedure. It's "a pointer to an array of size 2, containing cClass
es".
1 That &
to the right of function parameters means it can only be called on lvalues (the function is "&
-qualified").
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With