使用NULL参数实例化模板类

时间:2012-09-28 02:13:02

标签: c++ templates g++

我从其他Stackoverflow线程(如this)中了解到,在编译时评估了Template参数。 此外,非类型模板参数应该是常量表达式,整数表达式或指向具有外部链接的对象的指针。

而且,我在Makefile中的g ++命令中没有使用--std = c ++ 0x。

那么,是否可以实例化一个模板类,其中NULL作为参数传递?

// 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;

上面的代码在MS Visual Studio 2008上编译得很好。 在g ++上 - 我得到错误 - “转换为除了整数或枚举类型以外的类型不能出现在常量表达式中”

我在谷歌搜索后尝试了一些选项 -

声明“extern void * MY_INVALID_VAL;”在头文件中 - 包含它并执行   void MY_INVALID_VAL = NULL;在模板实例化之前。   在这种情况下,我得到错误“MY_INVALID_VAL不是类型'void '的有效模板参数,因为它不是常量指针”

所以我的问题是 - 如果不使用c ++ 0x标准,是否无法使用NULL参数实例化模板类?

谢谢!

编辑:

感谢所有评论和感谢引用标准草案中的确切部分。

只需列出我尝试过的东西 -

1)直接传递“0”不起作用。    我得到的错误是 - “无法将'0'转换为模板参数void *”

2)声明static const void * my_null = 0;并传递my_null不起作用。    它给出了错误 - “my_null不能出现在常量表达式中”

3)尝试在其中一条注释中建议指向null Object(null object pattern)方法的指针    见下文 -

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;

我仍然得到错误 - “ptr不能出现在常量表达式中”

所以现在我想知道 - 我应该传递什么价值才能让它发挥作用? 或者没有可能使它工作? (我的意思是一种不涉及使用c ++ 11标准的方法) 我没有-yet-找到一个将继续编译的值。

任何帮助表示赞赏(并且需要:-P)!

作为旁注,我还想问的另一件事是 - 是否有任何指针值可以用于非类型模板参数?

2 个答案:

答案 0 :(得分:6)

C ++ 98表示非类型模板参数应为

之一
  
      
  • 整数或枚举类型的整数常量表达式;或
  •   
  • 非类型模板参数的名称;或
  •   
  • 具有外部链接的对象或函数的名称,包括函数模板和函数 template-ids ,但不包括非静态类成员,表示为 id-expression ;或
  •   
  • 具有外部链接的对象或函数的地址,包括函数模板和函数 template-ids ,但不包括非静态类成员,表示为&amp; id-expression &amp;如果名称引用函数或数组,则为option;或
  •   
  • 指向成员的指针,如5.3.1所述。
  •   

空指针不属于此列表的任何项目,因此将空指针作为非类型模板参数传递无效。

C ++ 11将此列表更新为

  
      
  • 表示整数或枚举类型的非类型模板参数 template-parameter 类型的转换常量表达式(5.19);或
  •   
  • 非类型模板参数的名称;或
  •   
  • 一个常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部链接的对象的地址,或具有外部或内部链接的函数,包括函数模板和函数 template-ids 但排除非静态类成员,表示(忽略括号)为&amp; id-expression ,除了&amp;如果名称引用函数或数组,则可以省略,如果相应的 template-parameter 是引用,则应省略;或
  •   
  • 一个求值为空指针值的常量表达式(4.10);或
  •   
  • 一个常量表达式,其值为null成员指针值(4.11);或
  •   
  • 指向成员的指针,如5.3.1所述。
  •   

更新的要求确实涵盖了空指针。因此,要将空指针用作非类型模板参数,必须使用C ++ 11。

答案 1 :(得分:0)

试试这个:

static const void* my_null_pointer = 0;
typedef A<void *, my_null_pointer, 1> ClassA;

这样的东西对我来说也适用于MSVC和gcc。 传递0作为模板参数也应该

typedef A<void *, 0, 1> ClassA;