As per http://en.cppreference.com/w/cpp/language/type_alias, aliases are block-level declarations. It doesn't say anything special about template aliases, so it should be read that template aliases are block-level declarations as well.
However, it is impossible to use template aliases at block level. The errors are different depending on the compiler - while g++ gives a meaningful message, saying that templates are not allowed at block scope, clang is completely cryptic. (example: http://coliru.stacked-crooked.com/a/0f0862dad6f3da61).
Questions I have so far:
Does cppreference fail to specify that template aliases can not be used at block scope? (Or do I need to take a reading course?)
Are the compilers correct in denying template aliases on block level (the feature I find very interesting for my particular coding habits)
If the answer to the second is Yes, what might be the rationale for this? Why would compiler deny me this pure syntax sugar?
An alias template is [temp.alias]
A template-declaration in which the declaration is an alias-declaration (Clause 7) declares the identifier to
be a alias template. An alias template is a name for a family of types. The name of the alias template is a
template-name.
And if we look at 14.2 [temp] we have
A template-declaration can appear only as a namespace scope or class scope declaration. In a function
template declaration, the last component of the declarator-id shall not be a template-id.
So yes cppreference is off saying that it can be declared at block scope and your compilers are correct. If you do click on the link of block declarations It will bring you to a list of declarations and in that it has Template declaration and in there it has
declaration of a class (including struct and union), a member class or member enumeration type, a function or member function, a static data member at namespace scope, a variable or static data member at class scope, (since C++14) or an alias template (since C++11) It may also define a template specialization.
As for why the standard says that templates can only be declared in namespace scope or class scope I like James Kanze answer
The problem is probably linked to the historical way templates were implemented: early implementation techniques (and some still used today) require all symbols in a template to have external linkage. (Instantiation is done by generating the equivalent code in a separate file.) And names defined inside a function never have linkage, and cannot be referred to outside of the scope in which they were defined.
The compilers are behaving correctly.
Section 14 of the C++14 standard:
A template-declaration can appear only as a namespace scope or class
scope declaration.
Related
#include <iostream>
typedef int Name;
Name func(int){
return 0;
}
int main(){
}
Consider the above code, I can't find a bullet in [basic.lookup.unqual] that can interpret how to lookup Name for definition of func. I will cite some potential rules here:
A name used in global scope, outside of any function, class or user-declared namespace, shall be declared before its use in global scope.
A name used in a user-declared namespace outside of the definition of any function or class shall be declared before its use in that namespace or before its use in a namespace enclosing its namespace.
In the definition of a function that is a member of namespace N, a name used after the function's declarator-id shall be declared before its use in the block in which it is used or in one of its enclosing blocks ([stmt.block]) or shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N's enclosing namespaces
Please note the emphasized parts, it seems that my case does not satisfy these bullets, because Function definitions have the form
function-definition:
attribute-specifier-seq(opt) decl-specifier-seq(opt) declarator virt-specifier-seq(opt) function-body
Let me analyze the first bullet. It says outside of any function,but according to the Function definitions rule, I think that Name is within the function(definition), bullet 1 isn't satisfied. Bullet 2 is similar with that of bullet 1. Bullet 3 says that the name used after the function's declarator-id, in my case, the Name is used before the function's declarator-id. So what's the rule about this case to find the unqualified name Name?
My confusions:
In my example ,the Name,func ,(int) and { return 0;}(function body) are all parts of that function definition,So:
what is outside of any function,such as the func in my example,where's area of outside of that function?
what is outside of the definition of any function,such as the func definition in my example,where's area of outside of the definition of that function?
I think that Name is within the function(definition), bullet 1 isn't satisfied.
Bullet 1 didn't say "function(definition)". It said "outside of any function". It doesn't specify declaration or definition; merely "outside of any function".
Since being inside or outside of a "function" is not a defined concept, it must be read as plain English. Is a function prototype "outside of the function"? Visually speaking, there's nothing special about a function prototype that is suggestive of an inside/outside distinction. By contrast, the function body's block scope does suggest an inside/outside distinction.
The intent of the text of course is quite obvious; it's talking about the function body. The rule equates "function", "class" and "namespace", all of which have a block that defines scoping for names. That is the most logical place for any inside/outside distinction, so it seems pretty obvious that it's saying that the global scope consists of everything that isn't in the scope of a function body, the scope of a class definition, or the scope of a namespace body.
So this can be easily handled with an editorial change.
Note that the committee recognizes the wording of this section (among others in that area) as somewhat defective, and there's a proposal for rewriting it into something more coherent in C++23. The new wording from the proposal completely rewrites this section.
The software project I lead occasionally uses nested namespaces as a means of indicating which parts of the library are intended to be internal and should not be considered user-facing. For example:
namespace project::detail {
// Hands off; library implementation internals
class Internal {};
int important_number(Internal internals);
}
Before C++17, the indentation would become somewhat dreadful (depending on the source code formatting), so we opted for defining functions out-of-namespace:
int
project::detail::important_number(Internal const internals)
{ ... }
Observe that although the type Internal was declared and defined in the project::detail nested namespace, it is not required to fully qualify the parameter type (i.e.):
int
project::detail::important_number(/*unnecessary*/ project::detail::Internal)
I have scoured en.cppreference.com and bits of the C++14 standard and have not found the place(s) that support the abbreviated function definition (the first example above). I am assuming the relevant rules did not change for C++17. Can anyone tell me which rules of the C++14/17 standard apply here--i.e. where does the standard support non-fully-qualified parameter types for out-of-namespace function definitions?
You're looking for unqualified name lookup and it can be found in the standard under basic.lookup.unqual
In the definition of a function that is a member of namespace N, a
name used after the function’s declarator-id shall be declared before
its use in the block in which it is used or in one of its enclosing
blocks or shall be declared before its use in namespace N or, if
N is a nested namespace, shall be declared before its use in one of
N’s enclosing namespaces.
Namespaces are in many was like classes with no constructors, no destructors, no inheritance, final, and only static methods and members. After all, this kind of classes can essentially be used only the way namespaces are used: a named scope for declarations and definitions.
... except that the above is not true, since classes can be templated - and namespaces cannot. There have been a couple of questions here on the site similar to "can I template a namespace", but what I'd like to know is - has the C++ standard committee ever considered a proposal to make namespaces templatable? If it has, was the proposal rejected? If it was, what were the reasons?
The inability to have a template namespace is actually just one way in which they differ from classes. Others would be things like new namespace, and sizeof (namespace) - how could a compiler implement that, given that a namespace may extend over many compilation units?
Looking just at template namespaces... While it can at times be hard to keep up with all the proposals for new C++ features, I don't recall ever seeing one that attempted to add a feature such as you describe.
Would it ever be considered, assuming someone were to write a proposal? As Stroustrup indicates in this interview (http://www.stroustrup.com/devXinterview.html):
For C++ to remain viable for decades to come, it is essential that
Standard C++ isn't extended to support every academic and commercial
fad. Most language facilities that people ask for can be adequately
addressed through libraries using only current C++ facilities.
As you indicate yourself, what you are asking for is basically already there: just use a templated class with static members. This seems to disqualify it as a potential new feature, at least in the eyes of Stroustrup.
How would ADL work if namespaces can be templated? Are we supposed to create special template deduction rules for ADL then?
More importantly, can you justify the added complexity to the language by demonstrating a use-case that can't be filled by, just make a template struct with only static members? If a template namespace is just like a gimped template struct, that doesn't seem to be very compelling.
Also. I understand you weren't satisfied with the other questions about namespace / template hybrids, but one point in this answer seems to be relevant to your question:
Why can't namespaces be template parameters?
Possibly difficult: A namespace isn't a complete, self-contained entity. Different members of a namespace can be declared in different headers and even different compilation units.
If a namespace is a template, how will this even work? Can you still "reopen" the namespace like you can with a regular namespace? If that's allowed, then what is the point of instantiation of the namespace?
It sounds like it could potentially be extremely complicated.
Also: Will the language still be easily parsable after your proposed feature?
One of the most vexing things in C++ is the need to write template often when defining templates that refer to other templates, in order to resolve ambiguity in the grammar regarding whether < is a less than operator or a template parameter list.
3.4.5 [basic.lookup.classref]
In a class member access expression (5.2.5), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (14.2) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template. If the lookup in the class of the object expression finds a template, the name is also looked up in the context of the entire postfix-expression and
— if the name is not found, the name found in the class of the object expression is used, otherwise
— if the name is found in the context of the entire postfix-expression and does not name a class template, the name found in the class of the object expression is used, otherwise
— if the name found is a class template, it shall refer to the same entity as the one found in the class of the object expression, otherwise the program is ill-formed.
If namespaces can be templates, don't we have to write template for them also, whenever you will refer to a template after a :: operator? For the same reason that foo::bar < 1 ... could be a namespace template bar inside of template foo with a non-type template parameter, or it could be a comparison of 1 with int foo::bar.
How do we disambiguate between that and the third possibility, foo is a namespace and bar is a regular class template inside of it`?
This question here piqued my interest a little. Is there anywhere in the C++ standard that specifies all declarations within a class must be parsed before any accompanying implementations of member functions? I've seen a few other questions similar to this but no references to the standard in any of the answers.
The Standard doesn't specify how the compiler should parse a translation unit. Instead, it specifies everywhere it is and is not valid to use any identifier to refer to a declaration.
3.3.2p5:
After the point of declaration of a class member, the member name can be looked up in the scope of its
class. [ Note: this is true even if the class is an incomplete class. ]
3.3.7p1:
The following rules describe the scope of names declared in classes.
The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration, but also of all function bodies, brace-or-equal-initializers of non-static data members, and default arguments in that class (including such things in nested classes).
A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.
If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.
A name declared within a member function hides a declaration of the same name whose scope extends to or past the end of the member function’s class.
The potential scope of a declaration that extends to or past the end of a class definition also extends to the regions defined by its member definitions, even if the members are defined lexically outside the class (this includes static data member definitions, nested class definitions, member function definitions (including the member function body and any portion of the declarator part of such definitions which follows the declarator-id, including a parameter-declaration-clause and any default arguments (8.3.6).
[class.mem] says:
-2- A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
For the class to be complete within function bodies then in general all declaration need to be parsed: without completely parsing all declaration you can't know if something that wasn't parsed would change the meaning. Although, possibly related to that is [basic.scope.class]/1 which says:
3) If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.
That means certain declarations could be used without parsing the entire class, because if another later declaration altered the meaning then the program would be ill-formed.
Of course the "as if" rule allows the compiler to choose any implementation as long as the user can't tell the difference, so maybe a compiler could choose to parse function bodies and then parse definitions as needed, but it would be hard to tell what's needed to process the member function definition (consider a function call which might call one of several overloaded functions, possibly involving enable_if-type tricks.)
This is the draft which explains C++ Programming Language Standard.
Programming Language C++ PDF
I think page 220 has some explanations on member functions.
I was interested to note that C++ (VSVC++ 2008 specifically) lets me declare a struct inline in a method.
e.g:
MyClass::method()
{
struct test{ int x;};
test t = {99};
}
My question is, how does this declaration work internally, and specifically does it have any negative performance implications?
how does this declaration work internally?
Exactly like a declaration at namespace scope, except that the name is only visible within the scope of the block it's declared in (in this case, the function body). UPDATE: as #Nawaz points out, there are one or two extra restrictions that apply to local classes: they cannot have static data members, and (in C++03, but not C++11) they can't be used as template type arguments.
does it have any negative performance implications?
No, apart from its scope (which only affects whether or not the code compiles), it is identical to any other class definition.
The main difference from defining the type inside the function scope or outside of it is, well, the scope. That is, if it is defined inside the function it will not be accessible outside of the function.
There are other differences though (at least in C++03, I have not rechecked C++11), you cannot have a static member or a template member in a local class. You cannot use that local class as argument to a template either (this limitation has been removed in C++11), and IIRC this is because the local class has internal linkage (rather than external for a namespace level class), and templates required the arguments to be of external linkage.