Sorry for the funny title.
Prior to C++0x, there are restrictions in the use of function-local structs (“local types”) as template arguments. My question is essentially if similar restrictions apply to anonymous structs. Specifically, in the context of a trait class:
template <typename T>
struct trait;
template <>
struct trait<int> {
typedef int type;
};
template <typename T>
struct trait<std::basic_string<T> > {
typedef struct {
T value;
} type;
};
trait<std::string>::type foo; // Is this valid?
template <typename T>
void f() { }
f<trait<std::string>::type> >(); // Is this?
template <typename T>
void g() { f<typename trait<T>::type>(); }
g<std::string>(); // And this?
Is this valid and reliable? It compiles in recent versions of GCC and LLVM but I’m still insecure whether this is strictly valid, and whether it’s understood by VC++ and ICC.
A Microsoft C extension allows you to declare a structure variable within another structure without giving it a name. These nested structures are called anonymous structures.
You can't "typedef a struct", that doesn't mean anything.
The C language contains the typedef keyword to allow users to provide alternative names for the primitive (e.g., int) and user-defined (e.g struct) data types. Remember, this keyword adds a new name for some existing data type but does not create a new type.
In Class Designer, a C++ typedef has the shape of the type specified in the typedef. If the source declares typedef class , the shape has rounded corners and the label Class. For typedef struct , the shape has square corners and the label Struct. Classes and structures can have nested typedefs declared within them.
For reference, the quote from the linked question in 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.
My interpretation is that the typedef struct
is creating an alias to an unnamed type and that it thus can't be used as a template type parameter. Further note that additionally in C typedef struct {} Foo;
is treated rather differently from struct Foo {};
giving precedent that the two forms are not equivalent (although admittedly that difference doesn't appear in C++).
Thus it would appear your first example works (since it's not using the unnamed type as a template type parameter), while the second and third examples would be technically invalid (since they do use it as a template type parameter).
Finally in closing I have to ask, is there a reason you can't name the struct instead of typedef
ing it?
EDIT: From 7.1.3/1:
...A typedef-name is thus a synonym for another type. A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does...
This strongly implies that using typedef
in such a way does not introduce a type suitable for use as a template type-parameter.
In the upcoming standard that restriction is removed from the language. The standard says in
14.3.1 [temp.arg.type] /1
A template-argument for a template-parameter which is a type shall be a type-id.
And a typedef is a valid type-id. As a matter of fact the next paragraph contains such an example:
14.3.1 [temp.arg.type] /2
template <class T> class X { };
template <class T> void f(T t) { }
void f() {
typedef struct { } B;
B b;
X<B> x3;
f(b);
}
(Where I have trimmed most of the other examples) The example shows that an unnamed type can be used as a class template argument both in class templates and function templates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With