3

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

而且,我没有在 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++ 上 - 我收到错误 - “转换为整数或枚举类型以外的类型不能出现在常量表达式中”

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

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

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

谢谢!

编辑:

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

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

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

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

3)尝试了评论之一中建议的指向空对象(空对象模式)方法的指针见下文 -

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 std 的方法)我还没有找到一个可以成功编译的值。

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

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

4

2 回答 2

6

C++98 说非类型模板参数应该是其中之一

  • 整数或枚举类型的整数常量表达式;或者
  • 非类型模板参数的名称;或者
  • 具有外部链接的对象或函数的名称,包括函数模板和函数模板ID,但不包括非静态类成员,表示为id-expression;或者
  • 具有外部链接的对象或函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示为 & id-expression,其中 & 是选项,如果名称指的是函数或数组;或者
  • 指向成员的指针,如 5.3.1 中所述。

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

C++11 将此列表更新为

  • 对于整数或枚举类型的非类型模板参数,模板参数类型的转换常量表达式(5.19);或者
  • 非类型模板参数的名称;或者
  • 一个常量表达式 (5.19),它指定具有静态存储持续时间和外部或内部链接的对象或具有外部或内部链接的函数的地址,包括函数模板和函数模板 ID,但不包括非静态类成员,表示(忽略括号)作为 & id-expression,但如果名称引用函数或数组,则 & 可以省略,如果相应的模板参数是引用,则应省略;或者
  • 计算结果为空指针值的常量表达式(4.10);或者
  • 一个常量表达式,计算结果为空成员指针值 (4.11);或者
  • 指向成员的指针,如 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.

于 2012-09-28T03:01:44.470 回答
1

试试这个:

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

类似的东西在 MSVC 和 gcc 上也适用于我。传递 0 作为该模板参数也应该有效。

typedef A<void *, 0, 1> ClassA;
于 2012-09-28T02:49:05.927 回答