Void指针作为C ++中的模板参数

时间:2015-10-13 16:21:41

标签: c++ templates gcc standards void

以下内容无法编译:

template<void *p>
class X {
// ...
};

int r;

int main()
{
    X<&r> x;

    return 0;
}

错误消息是

  

x.cc:10:6:错误:无法转换模板参数'&amp; r'到'void *'

明确地投射&amp; r到(void *)也没有帮助。错误消息变为:

  

x.cc:10:14:错误:无法将模板参数'(void *)(&amp; r)'转换为'void *'

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

修改

请注意使用例如int *而不是void *按预期工作。

编辑:(自己回答)

指定-std = c ++ 1z时 gcc HEAD 6.0.0 20151016(实验性)一起使用,既没有隐式也没有显式转换为& #34; void *&#34;。

确实 clang HEAD 3.8.0(主干250513)一起使用,并且至今已经(至少) clang 3.6.0(标签/ RELEASE_360 /最后)指定--std = c ++ 1z并显式转换为* void *&#34;。 没有明确的演员,clang抱怨如下:

  

x.cc:10:7:错误:转换为&#39; int *&#39;到&#39;无效*&#39;转换的常量表达式中不允许使用

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

2 个答案:

答案 0 :(得分:1)

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

  

[C ++ 11,4.10 / 2]类型为“指向cv T的指针”的prvalue,其中T是   对象类型,可以转换为类型为“指向cv的指针”的prvalue   无效”。将“指向cv T的指针”转换为“指向cv的指针”的结果   cv void“指向对象所在存储位置的开头   类型T驻留,就好像该对象是最派生的对象(1.8)   type T(即不是基类子对象)。空指针值   转换为目标类型的空指针值。

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

  

[C ++ 11,14.3.2 / 5]对每个进行以下转换   表达式用作非类型模板参数。如果是非类型   template-argument无法转换为对应的类型   模板参数然后程序格式不正确。

     

[...]

     

- 对于指向对象的类型指针的非类型模板参数,   资格转换(4.4)和数组到指针的转换   (4.2)适用;如果template-argument的类型为std :: nullptr_t,   应用空指针转换(4.10)。 [...]

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

答案 1 :(得分:0)

我无法引用你的章节和经文(欢迎编辑),但你在c ++中不允许做的事情。

模板参数必须在编译时知道。指针仅在链接时解析,除非:

  1. 它们在模板参数列表中使用= nullptr默认。

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

  3. 例如,这将编译:

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