以下内容无法编译:
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已经实现的。
答案 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 ++中不允许做的事情。
模板参数必须在编译时知道。指针仅在链接时解析,除非:
它们在模板参数列表中使用= nullptr
默认。
它们是成员函数指针( 在编译时是已知的,因为它们只是偏移量)。
例如,这将编译:
template<void * = nullptr>
class X {
// ...
};
int r;
int main()
{
X<nullptr> x;
return 0;
}