June 01, 2006
Living By the Rules: Part IIMaking Common Mistakes Legal
It's frustrating to have to add spaces between ">" symbols when you're wrapping up a declaration that involves nested templates. Many people's natural instinct is to jam them all together:
std::vector<std::pair<int, std::string>> vect; Today, that's illegal: The two ">" symbols at the end are treated as a shift-right, and the declaration is ill-formed. In the next version of the Standard, that will be legal. As long as you're unwinding template IDs, a non-nested ">>" is treated as two ">"s and not as a single token. This means that you have to be a little careful if you really want to have a shift-right somewhere in your template usage, but that's far less common. For example, the working draft of the new Standard gives this example of code that will be invalid:
To make it valid, you have to put parentheses around the arithmetic expression:
Y<X<(6>>1)>> x4; Another common problem occurs when template code uses a type name inside a friend declaration. Technically, the type name has to be what the Standard calls an "elaborated type specifier." That makes this usage illegal:
template <class Ty> class no_children
{ // template to block inheritance from Ty
no_children() {}
friend class Ty;
};
If it worked, this pattern would prevent deriving from the class final [4]. There's a problem, though: In the declaration friend class Ty, the name Ty is not an elaborated type specifier, so it can't be the target of a friend declaration. That's been changed, so that a broader range of syntactic elements can be used as the target of a friend declaration, and this code will be legal.
A common beginner's mistake is writing something like this:
The mistake is thinking that the line marked "mistake" applies the default constructor to the object being constructed, thus setting i and j to 0. Of course, we've all learned to patiently explain that what that line actually does is create an unnamed temporary object of type S, and immediately destroy it. That will still be a mistake, but there is a new syntax that allows a constructor to delegate part or all of its work to another constructor:
The line marked "changed" has a constructor as its initializer list. That tells the compiler to apply that constructor first, and then to execute the body of the constructor being defined [5].
|
|
||||||||||||||||||||||||||||||
|
|
|
|