Reputation:
I tried this example from "C++ Template - The Complete Guide" by Nicolai M. Josuttis
#include <iostream>
using namespace std;
template< typename T >
class List {
};
typedef enum { RED, GREEN, BLUE } *color_ptr;
int main() {
struct Local {
int x;
};
List< Local > l; // error : local type in template argument
List< color_ptr > l1; // error : unamed type in template argument.
return 0;
}
With g++ under Ubuntu 9.04, I got compiler errors. However, this piece of code was compiled successfully in Visual C++ 2008. And as I read from the book : "Template type arguments are the "values" specified for template type parameters. Most commonly used types can be used as template arguments, but there are two exceptions: 1. Local classes and enumerations( in other words, types declared in a function definition ) cannot be involved in template type arguments. 2. Types that involve unnamed class types or unnamed enumeration types cannot be template type arguments ( unnamed classes or enumerations that are given a name through a typedef declaration are OK. ) So is there a mistake in Visual C++ ?
Upvotes: 1
Views: 481
Reputation: 506837
There are many other cases where you find that book diverge from the behavior of VC++. Examples are the typename
and template
ambiguity tools and the binding of non-const references to rvalues.
In this case, of course the behavior of G++ is correct, as the book says. Try the following changes
typedef enum color_type { RED, GREEN, BLUE } *color_ptr;
template< typename T >
class List {
};
// not really local anymore :)
struct Local { int x; };
int main() {
List< Local > l;
List< color_type > l1;
}
The next C++ Standard (C++0x) allows local types as template arguments.
Please note what the book means with giving a name to a type with typedef. This does not apply to the following, because the name A
does not name the enumeration type, but a pointer type to it.
typedef enum { X } *A;
So, when you use A
or in your example color_ptr
, then you are not going safe. Technically, that name is a pointer type to a type without linkage, which is not allowed as a template argument.
Note that you may put Local
into an unnamed namespace to make the type local to the current translation unit, but still have the type acceptable as a type template argument. That way, if you just want to have a "scratch" type for something like a function object, the struct won't clash with a struct defined in a different file.
namespace {
// not really local anymore, but "translation unit local" :)
struct Local { int x; };
}
Upvotes: 3
Reputation: 881487
These are permissible extensions to the standard on MSVC's part. MS does a decent job documenting its compiler's options, conformance or deviance from standards, &c; in particular, as documented here, /Za
will tell the compiler to flag as errors deviations from the standard (which it peculiarly calls "ansi C++" instead of ISO;-).
Upvotes: 1
Reputation: 4186
Check to see if you are compiling with Microsoft extensions (/Ze).
Upvotes: 0