c++中Void指针作为模板参数

Void pointer as template argument in C++

本文关键字:参数 Void 指针 c++      更新时间:2023-10-16

以下代码无法编译:

template<void *p>
class X {
// ...
};
int r;
int main()
{
    X<&r> x;
    return 0;
}

错误信息是

x。Cc:10:6:错误:无法转换模板参数' &R ' to ' void* '

显式地将&r转换为(void *)也没有帮助。错误信息变成:

x。Cc:10:14:错误:无法转换模板参数' (void*)(&R) ' to ' void* '

标准的哪一部分规定了这种行为?GCC版本为 GCC version 5.2.1 20151003 (Ubuntu 5.2.1-21ubuntu2)

编辑:

请注意,使用int *代替void *可以正常工作。

编辑:(回答自己)

当指定-std=c++1z时,gcc HEAD 6.0.0 20151016(实验性)一起工作,既不隐式也不显式强制转换为"void *"。

可以与clang HEAD 3.8.0 (trunk 250513)一起工作,并且至少从clang 3.6.0 (tags/RELEASE_360/final)指定——std=c++1z并显式强制转换为"void *"开始。如果没有显式强制转换,clang会报错如下:

x。Cc:10:7:错误:在已转换的常量表达式

中不允许从'int *'转换为'void *'

负责修复c++语言规范中的这个错误的是N4268, clang已经实现了。

通常情况下,允许对任何指向void*的指针进行转换。

[c++ 11,4.10/2]类型为"指向cv T的指针"的右值,其中T为an对象类型,可以转换为"指向CV的指针"类型的右值无效"。将"指向cv T的指针"转换为"指向的指针"的结果"CV void"指向对象所在的存储位置的开始类型T的对象驻留,就好像该对象是的最派生对象(1.8)类型T(也就是说,不是基类子对象)。空指针值转换为目标类型的空指针值。

但是,对于非类型模板参数,指定某些转换:

[c++ 11, 14.3.2/5]分别执行以下转换用作非类型模板参数的表达式。如果是非类型模板参数不能转换为对应参数的类型模板参数,则程序格式错误。

[…]

—用于指向对象的指针类型的非类型模板形参;限定转换(4.4)和数组到指针的转换(4.2)适用;如果模板参数类型为std::nullptr_t,应用空指针转换(4.10)。[…]

通过省略

,我们可以推断这种转换是不允许的。

我不能马上引用你的章节(欢迎编辑),但是你试图做的事情在c++中是不允许的。

模板形参必须在编译时已知。指针只在链接时解析,除非:

  1. 默认使用模板参数列表中的= nullptr

  2. 它们是成员函数指针(其中在编译时是已知的,因为它们仅仅是偏移量)。

例如

,这将编译:

template<void * = nullptr>
class X {
    // ...
};
int r;
int main()
{
    X<nullptr> x;
    return 0;
}