为什么具有无效继承的类型在作为模板参数传递时不会被拒绝?
众所周知,类不能从基本类型和标记为final
的类继承。但尽管如此,下面提供的代码在 Clang 12 和 GCC 9 上编译时没有任何问题。
#include <type_traits>
template<typename T>
struct Inheriter : public T{};
int main()
{
std::void_t<Inheriter<int>>();
}
As we all know, classes can't be inherited from fundamental types and from classes that are marked as final
. But despite that, the code presented below compiles without any problems on Clang 12 and GCC 9.
#include <type_traits>
template<typename T>
struct Inheriter : public T{};
int main()
{
std::void_t<Inheriter<int>>();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
根据[expr.type.conv]:
含义
T()
当T
是void
(如您的情况)是无操作,而void_t
是 定义为(根据[temp.alias])这意味着如果提供了有效类型,那么它将始终变为
void
。这是我的看法:
代码在语法上是正确的,如果类型替换成功,则可以证明它是无操作。根据 as-if 规则,编译器可以证明该程序如果没有这一行,则完全具有相同的运行时行为,因此可以安全地完全忽略它。我可以在 MSVC、GCC 和 Clang 中重现此行为。
Per [expr.type.conv]:
Meaning
T()
whenT
isvoid
(as in your case) is a no-op, andvoid_t
is defined as (per [temp.alias])Meaning that if a valid type is supplied, then it will always become
void
.Here's my take:
The code is syntactically correct, and if type substitution succeeds it is provably a no-op. Per the as-if rule, the compiler can prove that the program without this line altogether has identical runtime behavior, and therefore it is safe to ignore it completely. I can reproduce this behavior in MSVC, GCC, and Clang.
如果模板特化
Inheriter
被实例化,则只会因继承而出现错误。实例化。简单地使用特化(例如作为模板参数)不会导致隐式实例化。粗略地说,类模板特化的隐式实例化仅在需要类完整或依赖于类完整性的上下文中使用时才会发生。
std::void_t
被定义为此别名模板中没有任何内容要求模板参数是完整类型。因此,不会发生隐式实例化。
因此,该程序是格式良好的,编译器不应拒绝它。
There will only be an error due to the inheritance if the template specialization
Inheriter<int>
is instantiated.Simply using the specialization, e.g. as a template argument, does not cause implicit instantiation. Roughly speaking implicit instantiation of the class template specialization happens only if it is used in a context that requires the class to be complete or otherwise depends on class completeness.
std::void_t
is defined asThere is nothing in this alias template that requires the template argument to be a complete type. As a consequence no implicit instantiation will happen.
The program is therefore well-formed and the compiler should not reject it.
编译器要求代码没有句法错误。样品片段没有。只有创建
继承
对象时,编译器才能提出任何错误(例如您期望的错误)The compiler requires that the code be free of syntactic errors. And the sample snippet doesn't have any. Only when you create an
Inheriter
object can the compiler raise any errors (such as the ones you are expecting)