当前位置: 首页 > 知识库问答 >
问题:

引用的静态转换强制模板实例化,其中不完整类型可以

鲜于华容
2023-03-14

以下代码无法在gcc 7.3.0和clang 6.0.0上编译(但在MSVC下似乎编译得很好):

#include <utility>

struct IncompleteType;

template<typename T>
struct Container {
    T value;
};

using Uninstantiatable = Container<IncompleteType>;

auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
    throw 1;
}

我得到的错误是:

<source>:7:7: error: field has incomplete type 'IncompleteType'
    T value;
      ^
<source>:12:24: note: in instantiation of template class 'Container<IncompleteType>' requested here
auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
                       ^
<source>:3:8: note: forward declaration of 'IncompleteType'
struct IncompleteType;
       ^
1 error generated.
Compiler returned: 1

自己在这里试试:https://godbolt.org/g/5AW37K

但是,如果我将第10行替换为

using Uninstantiatable = IncompleteType;

就像@Jarod42提到的,如果删除Container:的定义,它会再次编译http://godbolt.org/g/ue9iwC它看起来像gcc和clang,因此只有在定义了模板类时才实例化它。

在这两种情况下,我只是试图将一个常量ref复制到一个常量ref,所以我希望无论类型是什么,都能这样做,如果类型本身不完整,这确实会起作用。标准是否规定在此触发模板实例化,或者gcc和clang的行为是否不正确?

请注意,上面代码中的模式取自gcc的std::is_constructible实现,当我尝试复制包含带有不完整类型参数的模板类的const ref的元组时触发了错误,所以是的,这发生在实践中。

共有2个答案

穆锋
2023-03-14

如果不实例化模板化的类,则不会出现错误。

 using Uninstantiatable = IncompleteType;

表示您仅在不完整类型上生成引用。在未定义的类型上有一个引用或指针是可以的,因为编译器只需要在这里生成指针的代码。但如果实例化类:

template<typename T>
struct Container {
    T value;
};

这里你需要的是T的定义,它不是指针或引用,而是类型本身,这里没有定义。因此,编译器无法生成实例,因为它不知道有关的任何信息。

decltype(static_cast<Uninstantiatable const&>) 

意味着您实例化了模板,这会导致错误。这与您只需要在该语句中引用这一点无关。它必须生成模板本身的实例,而这是无法完成的,因为那里的“t”不是如上所述的。

锺离高丽
2023-03-14

根据标准隐式类,只有在需要完整对象时才应执行模板实例化[临时指令]/1:

[...],当在需要完全定义的对象类型的上下文中引用特化或当类类型的完整性影响程序的语义学时,类模板特化被隐式实例化。

正如Jarod的评论中指出的,如果不提供容器的定义,Unintatiable独立于InCompleteType的完整性,是一个不完整的类型和代码编译。此外,这个static_cast显然独立于对象的完整性。所以我认为这是gcc和clang的编译器错误。

 类似资料:
  • 从上面的标题来看,目前我遇到了一个问题,即无法从一个模型类转换到另一个模型类。我写的代码有问题吗?请随时向我询问更多信息。非常感谢。 我怀疑: 这种方法“selectTheOldFnException”有一些错误,那就是使用了hibernate,但我不确定这个理论。 REST控制器 使用HIBERNATE-MatchingEngine选择POJO。班 POJO班 例外代码

  • 问题内容: 我在一个新项目中将Swift样板代码用于Core Data。我的文件有一个定义的单一实体()和一个属性()。 我有一个看起来像这样的文件: 当我运行它时,它起作用: 我什至可以进入iOS模拟器正在使用的SQLite数据库,并确认已添加该行。 但是,当我运行与上面完全相同的代码,但使用而不是时,出现了与…行关联的错误消息,导致崩溃。如果我继续执行,则每次执行线程1时它都会到达并位于线程1

  • 强制类型转换 隐式类型转换:隐式类型转换又称为自动类型转换,隐式类型转换可分为三种:算术转换、赋值转换和输出转换。 显式类型转换:显式类型转换又称为强制类型转换,指的是使用强制类型转换运算符,将一个变量或表达式转化成所需的类型,这种类型转换可能会造成数据的精度丢失。 数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题。 转换的方法有两种: 自动转换(隐式转换):遵循一定的规则

  • 我将调用(used)的响应传递给一个类,并尝试将其强制转换到我的模型类。由于我对调用使用的是registfit,因此它在使用GSON将其转换为模型类对象之前,根据服务器的响应生成一个链接的hashmap。(这就是我所理解的,如果我错了请纠正我)。我已经附加了一个使用response对象进行调试时可以看到的图像。如何将此响应转换为我的模型类或类型对象的对象。当我试图将类型对象强制转换到活动中的模型类

  • 我有一门课: 问题是,只有我实例化了那个类,它才会运行。 不管怎样,我怎么能强迫它运行呢?

  • 本文向大家介绍C#中的自动类型转换和强制类型转换,包括了C#中的自动类型转换和强制类型转换的使用技巧和注意事项,需要的朋友参考一下 前面已经认识了不同的数据类型,你们有没有尝试过让不同的数据类型进行运算呢? 运行结果是:1 我们把一个整型的变量赋值给了一个浮点型的变量,可以正常的输出,如果我们把一个浮点型的变量赋值给一个整型的变量呢? 这样就会报错。 为什么呢?因为我们之前说过,变量就像一个容器,