为什么具有无效继承的类型在作为模板参数传递时不会被拒绝?

发布于 2025-01-19 07:27:23 字数 304 浏览 3 评论 0原文

众所周知,类不能从基本类型和标记为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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅唱々樱花落 2025-01-26 07:27:23

根据[expr.type.conv]

如果初始值设定项是带括号的单个表达式,则类型转换表达式等效于相应的强制转换表达式。否则,如果类型为 cv void 且初始值设定项为 () 或 {}(包扩展后,如果有),则表达式为 void 类型的纯右值,不执行初始化

含义 T()Tvoid (如您的情况)是无操作,而 void_t定义为(根据[temp.alias])

template<typename...> using void_t = void;

这意味着如果提供了有效类型,那么它将始终变为void

这是我的看法:

代码在语法上是正确的,如果类型替换成功,则可以证明它是无操作。根据 as-if 规则,编译器可以证明该程序如果没有这一行,则完全具有相同的运行时行为,因此可以安全地完全忽略它。我可以在 MSVC、GCC 和 Clang 中重现此行为。

Per [expr.type.conv]:

If the initializer is a parenthesized single expression, the type conversion expression is equivalent to the corresponding cast expression. Otherwise, if the type is cv void and the initializer is () or {} (after pack expansion, if any), the expression is a prvalue of type void that performs no initialization

Meaning T() when T is void (as in your case) is a no-op, and void_t is defined as (per [temp.alias])

template<typename...> using void_t = void;

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.

梦中的蝴蝶 2025-01-26 07:27:23

如果模板特化 Inheriter 被实例化,则只会因继承而出现错误。实例化

简单地使用特化(例如作为模板参数)不会导致隐式实例化。粗略地说,类模板特化的隐式实例化仅在需要类完整或依赖于类完整性的上下文中使用时才会发生。

std::void_t 被定义为此

template<typename...>
using void_t = void;

别名模板中没有任何内容要求模板参数是完整类型。因此,不会发生隐式实例化。

因此,该程序是格式良好的,编译器不应拒绝它。

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 as

template<typename...>
using void_t = void;

There 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.

说好的呢 2025-01-26 07:27:23

编译器要求代码没有句法错误。样品片段没有。只有创建继承对象时,编译器才能提出任何错误(例如您期望的错误)

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文