struct Simple { int a; }; template <typename T, int T::*U> struct Test { void Foo(T *obj, int v) { if (U != 0) obj->*U = v; } }; int main(int argc, const char **argv) { Test<Simple, &Simple::a> t1; // ok Test<Simple, 0> t2; // error, but should not be (works in MSVC 7/8) Simple s; t1.Foo(&s, 5); } Note: it also won't let you specify a default parameter of 0 for the template parameter: template <typename T, int T::*U = 0> struct Test // won't do this either MSVC 7/8 handle the first case, but also can't handle the default parameter (they crash with an internal compiler error). MSVC 7/8 also won't handle specialization of the Foo function for the 0 case, though the resultant code generated is the same since the branch is optimized out. I only mention this to give you some other nuances to check for once the base bug is fixed.
Comeau gives the following error: "ComeauTest.c", line 19: error: argument of type "int" is incompatible with template parameter of type "int Simple::*" Test<Simple, NULL> t2; // error, but should not be (works in ^
icc gives essentially the same error as that one mentioned by Andrew for Comeau (not surprisingly). As a workaround, you can always use an explicit cast: Test<Simple, (int Simple::*)0> t2; I believe the code is ok anyway, see 4.11/1. W.
The casting work-around doesn't compile under GCC. It requires that the template parameter be a constant-expression (which is true), which results in the following error: error: a casts to a type other than an integral or enumeration type cannot appear in a constant-expression I have yet to be able to figure out a work-around. MSVC allows the cast, but works with or without it.
Nothing to fix here, besides maybe the casting bit in c++98 mode which is PR10541. *** This bug has been marked as a duplicate of bug 10541 ***