sskanitk
sskanitk

Reputation: 475

Instantiating a template class with NULL argument

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

Answers (2)

bames53
bames53

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

blinnov.com
blinnov.com

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

Related Questions