der folgende (minimierte) Code compiliert anstandslos (auch bei
-pedantic -ansi -Wall -Wextra) mit g++ 3.4.4 / 4.2.4 auf Solaris sowie
g++ 4.3.3 auf Linux. Ein C++ Code-Analysator stolpert jedoch darüber
und auch der Comeau-Online-Compiler spuckt an der gleichen Stelle eine
Fehlermeldung aus.
-----8<-----
#include <iostream>
template<typename T_TYPE>
class TArray {
T_TYPE array[2];
};
struct t_outer {
struct {
struct t_inner {
char foo[4];
};
TArray<t_inner> bar;
} element;
};
int main() {
t_outer test;
std::cout << sizeof(test) << "\n";
}
-----8<-----
Comeau:
ComeauTest.c(16): error: a template argument may not reference an unnamed type
TArray<t_inner> bar;
^
Wer hat hier Recht, GCC oder Comeau?
(Ich vermute mal letzterer.)
Und wo finde ich dazu was zum genauer Nachlesen im Standard?
(Daß sich das Problem leicht mit einem Namen für die mittlere struct
korrigieren läßt, weiß ich schon, aber mit einem Verweis auf den
Standard hat ein Bug-Report deutlich bessere Chancen.)
Du vermutest richtig.
> Und wo finde ich dazu was zum genauer Nachlesen im Standard?
14.3.1/2:
A local type, a type with no linkage, an unnamed type or a type compounded
from any of these types shall not be used as a template-argument for a
template type-parameter.
Und ich denke der paragraph der t_inner internal linkage gibt ist folgender:
3.5/5:
In addition, a member function, static data member, class or enumeration of
class scope has external linkage if the name of the class has external
linkage.
("class" wurde korrigiert zu "named class" im c++0x draft) In diesem fall
hat die klasse garkeinen namen, also hat der member auch keine external
linkage (und auch keine internal, weil er nicht in der vorherigen liste
auftaucht). Allerdings glaube ich der vorherige paragraph der den sachen
external linkage gibt sollte sagen:
- a named class that is not a member of another class (clause 9), or an
unnamed class that is not a member of another class defined in a typedef
declaration in which the class has the typedef name for linkage purposes
(7.1.3);
Momentan denke ich dass wenn es einfach sagt "a named class", es tatsächlich
t_inner external linkage gibt. Oder aber man ändert 3.5/5 sodass es sagt "if
and only if" anstatt einfach nur "if". Was denkt ihr?
Man könnte natürlich vermuten dass comeau die klasse als template argument
ablehnt weil es mit einem type ohne linkage "compounded" ist, aber selber
external linkage hat. Ich denke aber nicht dass das der fall ist, denn wenn
t_inner wirklich external linkage hat, denke ich wird es für den compiler
unmöglich einen eindeutigen namen zu manglen der dann auch diese klasse
gegeneinander in mehreren TUs linkt. Also denke ich t_inner hat tatsächlich
keine linkage.
In dem von mir zitierten Paragraphen wurden "unnamed types" ja eh schon
ausgeschlossen, also braucht man sich eigentlich gar nicht mehr um die
Linkage zu kümmern.
> Man könnte natürlich vermuten dass comeau die klasse als template argument
> ablehnt weil es mit einem type ohne linkage "compounded" ist, aber selber
> external linkage hat.
Meine Vermutung wäre - basierend auf der Fehlermeldung - eher gewesen, daß
er sich darüber beschwert, daß es mit einem Typ ohne Namen compounded ist.
Eine "unnamed" klasse bezeichnet eine klasse ohne einen identifier in ihrem
kopf: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#406 . In
unserem fall haben wir eine named klasse - der name ist "t_inner".
Natürlich ist der code so oder so ill-formed da t_inner ja compounded ist
aus einem unnamed type, insofern hast du natürlich recht denke ich. Aber ich
wollte eher auf den ungenauen text zur linkage von t_inner aufmerksam
machen, weil mir das aufgefallen ist beim "nachforschen" :)
> Natürlich ist der code so oder so ill-formed da t_inner ja compounded ist
> aus einem unnamed type.
Sorry ich glaub ich liege da falsch. Das würde ja nur zutreffen wenn der typ
ohne linkage ein sub-typ währe, wie etwa "struct X { struct { } F; };",
"void(*)(WithoutLinkage)"; etc. Aber es gibt einen defect report zu ersterem
( defect#62 ), und ein anderer ersetzt den kompletten paragraph (und
offenbar wurde er in c++0x entfernt ^^), da ja z.B "void*" auch ein "unnamed
type" ist :)
Insofern würd ich schon sagen dass der aktuelle fall auf "linkage" basiert
(und ich denke ich werde hier einen defekt report melden um die linkage
klarer zu definieren), der code aber nicht ill-formed aufgrund dem
"compounded" satz ist, weil er ja eher genau das gegenteil macht, nämlich
als teil eines anderen types fungiert :)