Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiating a template class with NULL argument

Tags:

c++

templates

g++

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?

like image 428
sskanitk Avatar asked Mar 02 '26 06:03

sskanitk


1 Answers

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.

like image 150
bames53 Avatar answered Mar 03 '26 20:03

bames53



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!