Question

There is this code:

class A;

template <class T>
void fun() {
   A a;
}

class A { 
public: 
   A() {  } 
};

int main() { 
   fun<int>(); 
   return 0;
}

g++ 4.5 and g++ 4.7 compiles this without error. But clang++ 3.2 (trunk) gives this error:

main.cpp:5:6: error: variable has incomplete type 'A'
   A a;
     ^
main.cpp:1:7: note: forward declaration of 'A'
class A;
      ^

Which compiler is right then according to C++ standard?

Was it helpful?

Solution

Which compiler is right then according to C++ standard?

Both are correct. This is an ill-formed program. Emphasis mine:

N3290 14.6¶9
If a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is done, and if the completeness of that type affects whether or not the program is well-formed or affects the semantics of the program, the program is ill-formed; no diagnostic is required.

That clang++ and other compilers do issue a diagnostic here is a nice-to-have added feature, but a diagnosis is not mandatory. That clause "the program is ill-formed; no diagnostic is required" gives a compiler developer free reign to do just about anything in such circumstances and still be compliant.

OTHER TIPS

Clang is correct, as far as I know. At your function fun, you do not know the size of A, and since your allocating an A, you need to know it's size. In my opinion, gcc is way to forgiving here.

clang++ is using the correct behavior, this is described in section 4.6/9 of the standard (n1905).


Templates 14.6/9 Name resolution

If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.


To put things in simpler terms; if the name is not dependent on a template-parameter it should be in scope where the definition is found; therefore you'll need to define A before your definition of template<typename T> void fun ().

Comeau's compiler does not like it either:

"ComeauTest.c", line 5: error: incomplete type is not allowed
     A a;
       ^

However my attempts at finding chapter and verse in the C++ standard were fruitless. It seems hidden in between the lines and interactions of "point of instantiation", "name resolution". Paragraphs 14.6/8 and 14.6/9 of the 2003 standard seem relevant.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top