显式转换模板非类型参数时出错
Error when explicitly converting a template non-type parameter
考虑以下代码:
class Base{};
class Derived: public Base{};
template<Base& b> // references (and pointers) can be used as non-types
void f(){}
int main()
{
Derived d;
// f(d); // Error, template type must match exactly
f<(Base&)d>(); // Error here, why?!
}
我理解为什么注释调用失败了:模板类型必须完全匹配。然而,我尝试在第二次调用中强制转换,并得到此错误(gcc5.2):
错误:'d'不是'Base&'类型的有效模板参数,因为它不是具有外部链接的对象
如果我使Derived d;
全局相同的错误。Clang更有帮助,它说
…注意:候选模板被忽略:无效的显式指定模板形参'b'的实参
我的问题是:上面的代码是否合法?如果不是,有什么原因吗?
此答案假设c++ 11或更高版本
有两个问题:
1)非类型模板形参[temp.arg.nontype]/p1
对于引用类型或指针类型的非类型模板形参常量表达式的值不能指向(或者对于指针类型,不能是的地址):
-子对象(1.8),
2)对象的地址在编译时应该是可用的。总结(temp.arg 。Nontype]/p1 and [expr。Const]/p5因此,它应该具有静态存储时间。
把这两点放在一起,你会得到下面的编译
class Base{};
class Derived: public Base{};
template<Base& b> // references (and pointers) can be used as non-types
void f(){}
Base obj; // Static storage duration
int main()
{
f<obj>();
}
<<p> 生活例子/kbd> From [temp.arg.nontype]:
对于非类型的模板形参, 模板实参必须是的转换后的常量表达式 (5.20)模板参数的类型。
这里有两个问题。首先,d
没有链接,所以你不能在常量表达式中引用它。这是一个简单的修复:
Derived d;
int main() {
f<d>(); // still an error
}
现在,我们有另一个问题。我们进入下一个句子:
对于引用类型或指针类型的非类型模板参数常量表达式的值不能指向(或者对于指针类型,不能是的地址):
(1.1) -子对象(1.8),
我们试图将引用作为Derived
的子对象(基类子对象)。无论链接如何,这都是不允许的。
相关文章:
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 如何解决一元"*"(有"字符")错误的无效类型参数?
- "std::shared_ptr":不是参数"_Ty"的有效模板类型参数
- 具有可变参数非类型参数的模板专用化
- 函数类型参数的模板参数推导
- PowerShell 使用结构类型参数调用 C++ DLL 的导出函数
- 对于非常量指针类型的参数,未调用具有常量指针模板类型参数的功能
- 为模板传递非类型参数 agument
- 为什么带有类型参数的运算符 () 可以应用于 result_of 上下文中的类型?
- 使用其他模板类型参数作为要在函数签名中使用的类型别名声明
- 如何避免具有相同类型参数的函数中的错误
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- c++非类型参数包扩展
- 如何实现对参数顺序不可知的std::same_as的广义形式(即对于两个以上的类型参数)
- 在不同的模板参数包之间分发非类型参数包
- 如何在使用容器和字符串时强制使用显式分配器类型参数
- c++:为什么我在给出模板函数的所有类型参数时都会出错,而在省略参数时还好
- 使用bool非类型参数实例化类模板时出错
- 使用模板类型参数时出错
- 显式转换模板非类型参数时出错