views:

809

answers:

1

Consider the following code:

template<int* a>
class base {};

int main()
{
    base<(int*)0> test;
    return 0;
}

Both Comeau and MSVC compile this without issues (except for Comeau warning about an unused variable), while GCC fails on the base<(int*)0> test; line, stating

In function `int main()': a casts to a type other than an integral or enumeration type cannot appear in a constant-expression

template argument 1 is invalid

What exactly is it complaining about? And who's right -- should this code compile? It's worth noting that my GCC version is extremely old (3.4.2) so that may have something to do with it. Thanks.

+7  A: 

From a draft standard (emphasis added):

14.1.3 A non-type template-parameter shall have one of the following (option-
  ally cv-qualified) types:
  ...
  --pointer to object, accepting an address constant  expression  desig-
    nating a named object with external linkage,
  ...

Apparently, it's not legal to instantiate a template with a null pointer, as a null pointer doesn't point to a "named object with external linkage".

Managu
Related SO: http://stackoverflow.com/questions/275871/how-to-overcome-gcc-restriction-could-not-convert-template-argument-0-to-foo
Managu
jdehaan
This seems promising, but I don't think this answers why GCC and Comeau differ. For example, if I change to `base<(int*)1>`, *both* Comeau and GCC fail to compile. Additionally, if this requirement is from a 'draft', well, my GCC fails to compile it yet it's 4 years old, so if this was added to the standard during that time, then it wouldn't be that requirement that's making GCC choke.
GRB
People often quote from the draft because the standard itself is not available for free. There shouldn't be any significant differences between a final draft and the standard text, however. There hasn't been any new standard since 2003 (which was minor corrections), so your version of GCC is certainly younger than that requirement. The error message also sounds as if the compiler knew exactly what it is talking about. I'm tempted to think it is correct.
UncleBens
Alright, that's fair. But that still means that, if GCC is right, then Comeau is wrong to allow it to compile. Is it?
GRB
And to answer that question, see litb's comment
GRB
To clear it up though, the cited text is from a pre-standard 1996 draft. The Standard ('03) has there: "— pointer to object or pointer to function" and elsewhere it says that the argument should be "— the address of an object or function with external linkage,". So stricly according to '03 comeau is wrong, although being wrong on purpose, "conforming" to the yet-to-be-released c++0x instead.
Johannes Schaub - litb