Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous struct in typedef of trait class

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.

like image 948
Konrad Rudolph Avatar asked May 09 '11 16:05

Konrad Rudolph


People also ask

What is an anonymous struct?

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.

Can typedef and struct have same name?

You can't "typedef a struct", that doesn't mean anything.

What is a typedef struct?

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.

What is typedef class in C++?

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.


2 Answers

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 typedefing 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.

like image 187
Mark B Avatar answered Oct 28 '22 23:10

Mark B


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.

like image 32
David Rodríguez - dribeas Avatar answered Oct 29 '22 01:10

David Rodríguez - dribeas