You have learnt in lecture that there are many ways to create threads, and certain ways of creating threads actually don’t work.
Due to time constraints + how confusing this may be, this isn’t covered in the tutorial.
A brief recap of what you see in lecture:
|
|
The question is: why is this so cursed?
The Most Vexing Parse
C++ is a messy language that wants to modernize with fancy modern syntactic features but MUST keep things backwards compatible1.
This results in some syntactical ambiguity on whether something is a parameter or a function type specification.
The most vexing parse is a rule applied to handle such ambiguity.
Consider this:
|
|
What do you think line 2 means?
Generally, two schools of thought.
- foo is a char variable.
- It was made with argument ‘
Bar
’, where ‘Bar
’ has been constructed2.
- It was made with argument ‘
- foo is a function declaration3 that returns
char
.- It has an unnamed argument. The argument type is a pointer to a function4.
The standard chooses 2 as the interpretation. I can’t find the exact reason why in cppreference. Maybe you’d have better luck digging through the ISO standard. This is unfortunately left as an exercise for the reader… 😰
To resolve this ambiguity, we can either wrap the parameter in ()
(see t3
), or use uniform initialization (see t2
and t4
), i.e. {}
which was introduced in c++11.
You will get compile warnings if the vexing parse rule was applied to your code.
I don’t know the standard at the back of my hand, so here are some resources (and references to this writeup) to get you started on a deep-dive:
-
This mini writeup is mostly inspired by this wiki article that does a detailed job explaining the vexing parse rule. Read it to see more examples, gory details and types of vexing parses that happen, such as with C-style casting. Also, they talk about the common ambiguity resolution techniques.
TLDR: Use {} or lambdas for thread creation in assignments.
-
C++ must be backwards compatible with C code, or else the world will explode. ↩︎
-
More precisely, an anonymous instance of Bar (don’t worry, you don’t really need to know this). ↩︎
-
This might be confusing. How is it a function declaration without a {} body? This is probably because prototype functions are a thing. ↩︎
-
The wiki on vexing parse claims this is due to C++ type decay rules. ↩︎