Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring types and templates with the same name in C++

Tags:

c++

This is an academic question.

In the report for GCC bug 38764, there are the following examples:

template < class T > struct A {};
typedef A< float > A; // Accepted by Comeau, but not GCC
typedef ::A< float > A; // Accepted by GCC but not Comeau

I see why the code may be invalid, but I have trouble with one of the comments:

This code is invalid but the standard says for this case no diagnostic is required so both compilers are correct according to the standard.

Why is the code that is "invalid" accepted by the standard as valid? What does the standard say about this case in particular (template + type with the same name) and, in general, about namespaces for various entities (types, templates, functions, variables)?

like image 960
Alex B Avatar asked Jul 30 '10 01:07

Alex B


People also ask

What is templates name the type of templates?

Technical overview. There are three kinds of templates: function templates, class templates and, since C++14, variable templates. Since C++11, templates may be either variadic or non-variadic; in earlier versions of C++ they are always non-variadic.

Can templates be used for user defined data types?

Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.

How do you declare a template?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>( float original ); Template arguments may be omitted when the compiler can infer them.

What is template What is the need of template declare a template class?

Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. Generic Programming is an approach to programming where generic types are used as parameters in algorithms to work for a variety of data types.In C++, a template is a straightforward yet effective tool.


2 Answers

When the standard says "no diagnostic required", that means that the compiler does not have to produce an error or warning about the invalid code, but that the code's behavior is still undefined according to the standard and so it won't necessarily have predictable results. This is intended to make things easier on compiler-writers so that they are not obligated to detect relatively rare or particularly troublesome-to-detect sorts of programmer errors.

However, when a rule with "no diagnostic required" is violated, the compiler is not prohibited from detecting the invalid code and producing an error as a courtesy to the user. So in the example given, gcc is producing a courtesy diagnostic for one particular sort of invalid code, and Comeau is producing a courtesy diagnostic for a similar sort of invalid code. But neither diagnostic is required, so in neither case is the other compiler in violation of the standard by not producing an error message. The behavior of the code remains undefined in any case.

Several relevant standards quotations regarding class names and template names:

3.4/1

The name lookup rules apply uniformly to all names (including typedef-names (7.1.3), namespace-names (7.3) and class-names (9.1)) wherever the grammar allows such names in the context discussed by a particular rule. Name lookup associates the use of a name with a declaration (3.1) of that name. Name lookup shall find an unambiguous declaration for the name (see 10.2). [...]

7.1.3/3

In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type. [Example:

class complex { /* ... */ }; 
typedef int complex; // error: redefinition

—end example] Similarly, in a given scope, a class or enumeration shall not be declared with the same name as a typedef-name that is declared in that scope and refers to a type other than the class or enumeration itself. [...]

9.1/2

A class definition introduces the class name into the scope where it is defined and hides any class, object, function, or other declaration of that name in an enclosing scope (3.3). If a class name is declared in a scope where an object, function, or enumerator of the same name is also declared, then when both declarations are in scope, the class can be referred to only using an elaborated-type-specifier (3.4.4).

14/5

A class template shall not have the same name as any other template, class, function, object, enumeration, enumerator, namespace, or type in the same scope (3.3), except as specified in (14.5.4). Except that a function template can be overloaded either by (non-template) functions with the same name or by other function templates with the same name (14.8.3), a template name declared in namespace scope or in class scope shall be unique in that scope.

14.5.4/1

A primary class template declaration is one in which the class template name is an identifier. A template declaration in which the class template name is a template-id, is a partial specialization of the class template named in the template-id. A partial specialization of a class template provides an alternative definition of the template that is used instead of the primary definition when the arguments in a specialization match those given in the partial specialization (14.5.4.1). [...]

So, in summary:

  • typedefs cannot change the meaning of an existing type
  • class names can conflict with certain sorts of names, but not other class names
  • template class names do not include the template parameter, and cannot conflict with anything, even things that normal class names are allowed to conflict with
  • template specializations are considered to have the same template-id (name) as their corresponding generalized template, but they are (obviously) not the same type.

So there's a conflict in both directions here. The template name is not allowed to conflict with anything, and the typedef is not allowed to change A from a template class type to a specialization of a template class type.

like image 100
Tyler McHenry Avatar answered Sep 19 '22 05:09

Tyler McHenry


Why is the code that is "invalid" accepted by the standard as valid?

It isn't. If the code is invalid, then it is invalid.

The phrase no diagnostic required when applied to a syntax or semantic rule means that if your program violates the rule, the compiler doesn't have to issue an error message and it can continue compiling the program (or it can do anything else, really; the standard imposes no requirements on a compiler if you give it a program that violates such a rule).

In a sense, no diagnostic required is sort of like the undefined behavior of semantic rules: if you violate a rule for which no diagnostic is required, all bets are off.

like image 34
James McNellis Avatar answered Sep 21 '22 05:09

James McNellis