Reputation: 475
I understand from bunch of other Stackoverflow threads (like this) that Template arguments are evaluated at Compile Time. Also, non-type template-parameter should be either a constant expression, integral expression or pointer to an object with external linkage.
And, I am not using --std=c++0x in my g++ command in Makefile.
So, is it possible to instantiate a template class with NULL passed as argument?
// I have a template class like this -
template<class T, T invalidVal, int e> class A
{
static inline bool dummy(T value)
{
return 0;
}
}
#define MY_INVALID_VAL ((void *)0)
// Now I want create class from the above template class with
// T=void*, invalidVal=NULL & e=0
typedef A<void *, MY_INVALID_VAL, 1> ClassA;
The above code compiles fine on MS Visual Studio 2008. On g++ - I get the error - "a cast to a type other than an integral or enumeration type cannot appear in a constant-expression"
I tried out a few options after googling -
Declare "extern void *MY_INVALID_VAL;" in a header file - include it and do void MY_INVALID_VAL=NULL; before template instantiation. In that case, I get error "MY_INVALID_VAL is not a valid template argument for type 'void' because it is not a constant pointer"
So my question is - Is there no way of instantiating a template class with NULL argument without using c++0x standard?
Thanks!
EDIT:
Thanks for all the comments and thanks for citing exact section from standards' draft.
Just listing down the things I tried -
1) Passing "0" directly doesn't work. Error I get is - "could not convert '0' to template argument void *"
2) Declaring static const void *my_null=0; and passing my_null doesn't work. It gave error - "my_null can not appear in constant expression"
3) Tried the pointer to null Object (null object pattern) approach suggested in one of the comments See below -
class my_null
{
public:
my_null() { my_null_ptr = NULL; }
void * get() { return my_null_ptr; }
private:
void *my_null_ptr;
};
my_null my_null_obj;
my_null *ptr = &my_null_obj;
typedef A<void *, (void *)ptr, 1> ClassA;
Still I get error - "ptr can not appear in constant expression"
So now this has me wondering - what value should I pass to make it work? Or is there no possible to make it work? (I mean a way that does not involve using c++11 std) I haven't -yet- found a value that will succeed the compilation.
Any help appreciated (and needed :-P)!
As a sidenote, one more thing that I would want to ask is - is there any pointer value that I can use for non-type template argument?
Upvotes: 3
Views: 12989
Reputation: 88155
C++98 says that non-type template arguments shall be one of
- an integral constant-expression of integral or enumeration type; or
- the name of a non-type template-parameter; or
- the name of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as id-expression; or
- the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as &id-expression where the & is option if the name refers to a function or array; or
- a pointer to member expressed as described in 5.3.1.
Null pointers do not fall under any item of this list, and therefore it is not valid to pass a null pointer as a non-type template parameter.
C++11 updates this list to
- for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
- the name of a non-type template-parameter; or
- a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
- a constant expression that evaluates to a null pointer value (4.10); or
- a constant expression that evaluates to a null member pointer value (4.11); or
- a pointer to member expressed as described in 5.3.1.
The updated requirements do cover null pointers. Therefore, to use null pointers as non-type template arguments you must use C++11.
Upvotes: 6
Reputation: 305
Try this:
static const void* my_null_pointer = 0;
typedef A<void *, my_null_pointer, 1> ClassA;
Something like that worked for me on MSVC and gcc as well. Passing 0 as that template parameter should work as well.
typedef A<void *, 0, 1> ClassA;
Upvotes: 1