问题标签 [template-instantiation]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 对可能不完整的类型进行可选的安全检查强制转换
根据一个简单的、侵入式引用计数的对象系统,我有一个template<typename T> class Handle
,它打算用CountedBase
. Handle<T>
持有一个指向 a 的指针T
,以及在该指针上的析构函数调用DecRef
(在 中定义CountedBase
)。
通常,当尝试通过使用前向声明来限制标头依赖项时,这会导致问题:
作为解决方案,我重写Handle<T>::~Handle()
如下:
请注意,我在reinterpret_cast
这里使用而不是static_cast
,因为reinterpret_cast
不需要T
完整的定义。当然,它也不会为我执行指针调整......但只要我小心布局(T
必须有CountedBase
它最左边的祖先,不能虚拟继承它,并且在几个不寻常的平台上,一些额外的 vtable 魔法是必要的),它是安全的。
不过,如果我能在可能的情况下获得额外的安全层,那就太好了static_cast
。在实践中,定义T
通常在被实例化的时候就完成了,Handle::~Handle
这使它成为仔细检查T
实际继承自CountedBase
. 如果它不完整,我无能为力……但如果它是完整的,那么进行健全性检查会很好。
最后,这给我们带来了我的问题:
是否有任何方法可以进行编译时检查,当未完成T
时CountedBase
不会导致(虚假)错误?T
[通常的免责声明:我知道以这种方式使用不完整类型存在潜在的不安全和/或 UB 方面。尽管如此,经过大量跨平台测试和分析后,鉴于我的用例的某些独特方面,我确定这是最实用的方法。我对编译时检查问题感兴趣,而不是一般的代码审查。]
c++ - 完全专业化的模板功能
我在头文件中声明了一个函数模板。这个函数是一个归档器,它应该支持通过项目实现的其他几种类型(类)。这个想法是有一个基本模板声明,然后每个类都专门针对自己的类型。
此方法没有实现。现在我创建了一个类(比如,Header
),并且我希望它是可归档的。因此,我打算专门研究该方法。这是我现在拥有的:
我将函数声明为extern
因为我在 .cpp 文件中实现了它
这给了specialization after instantiation
. 我也尝试过其他组合:
- 直接在头文件中实现,通常建议用于模板:我得到“多重定义”
- .cpp 文件中的实现,没有在标题上声明:我
undefined reference
从另一个编译单元调用该方法时得到
那么执行此操作的正确方法是什么?
编辑:
最初我决定使用模板,因为逆过程,取消归档。基本上我可以写unarchive<Header>()
而不是unarchive_header()
看起来更合适。
我相信我还应该提到我正在使用 Android Studio 和 Gradle 构建系统进行编译,这就是我使用 gcc 而不是 g++ 的原因。我还为 gcc 提供了以下编译器标志:
-fpermissive
是一种绝望的行为。
c++ - 通过模板专业化进行依赖注入
lib.h:
客户端.cpp:
libmock.h:
生成文件:
使用 GCC 4.3.2(以及“IBM XL C/C++ for AIX, V11.1 (5724-X13)”),我得到了我期望的结果:
也就是说,我通过将新功能与提供比库提供的功能模板更专业的功能模板的对象链接,将新功能注入客户端。
但是,如果我使用“CC: Sun C++ 5.12 SunOS_sparc Patch 148506-14 2013/09/24”,则会收到以下错误:
我的解决方案必须适用于所有这三个编译器。我只是对 GCC 和 AIX 中的一些未定义行为感到幸运吗?我可以将一些选项传递给 Sun 编译器以使其工作吗?我正在尝试做的事情是否表明我没有完全理解这些模板概念?请赐教!
boost - 为什么这个成员函数是重复的?
我有一些可在 VS10 上运行并在其他几个平台上运行的代码,但在 VS2015 上会导致一个奇怪的错误。错误(在 Boost 内部的模板扩展中)非常奇怪,因为它指向一个没有的表单,const
并告诉我它在源中复制了紧邻它之前的前一个成员函数,这是一个添加 const 的变体。
这是我设法从有问题的程序中提取的一个最小示例。
我正在使用针对 x86(32 位)的 VS2015。
完整的错误是:
查看它报告的行
这里发生了什么?这似乎是boost::multi_index_container
.
c++ - 使用不同优化级别编译的不同翻译单元中的模板实例化
假设我有两个翻译单元,它们都使用std::string
. 我用 编译其中一个,-O3
另一个没有优化,然后将结果链接在一起。两个目标文件都将包含 instantiated std::string
,但我希望一个版本可以使用优化进行编译,而另一个则没有。链接器会在链接期间只选择其中一个吗?如果有,是哪一个?生成的可执行文件能否保证始终正常运行?
更新:由于这看起来是特定于实现的,因此将其缩小到 gcc 和 clang 行为是有意义的,因为它们都实现了定义明确且具体的 Itanium ABI,而不是试图从C++ 标准本身。
c++ - Does default argument of template class, instantiate the template?
Does the following default argument for the template instantiates a template with type EmptyClass
?
c++ - 模板化重载运算符的显式实例化
以下代码有效:
该using Foo::operator+;
指令带入Foo::operator+
外部查找范围,并且operator+
在调用中使用时cout
,采用默认模板值 11,结果如预期的那样:17 (=3+3+11)。
我的问题是如何更改using
子句以使用非默认模板值显式实例化operator+
函数?
线路using Foo::operator+<42>
不工作。
这是由于 ISO C++ 标准 7.3.3.5:使用声明不应命名模板 ID。
有没有解决的办法?
c++ - 模板类中的方法仅适用于某些模板参数正确
考虑以下模板类
现在让一些类Target
只提供成员函数func()
而不提供gunc()
,即
模板实例化Caller<Target>
是否有效?
GCC、clang 以及 VC++ 都接受这样的模板实例化。当然,调用Caller<Target>::gunc()
会导致错误,但Caller<Target>::func()
可以正常工作并按预期工作。
现在的问题是:这种宽容行为的背景是什么,C++ 标准中的相关段落在哪里。
c++ - GCC 6.1 显式模板实例化为默认构造函数提供未定义符号
把它放在一个名为 t.hpp 的文件中:
这在 t.cpp 中:
然后构建它(在 Linux 上):
然后查看共享对象中的构造函数:
如果你用 GCC 4.9 编译它应该什么都不显示。对于 GCC 5.1 或 5.3,它应该显示如下内容:
但在 GCC 6.1 中,它显示如下:
这意味着地图的默认构造函数不会在共享对象中发出,尽管它需要发出。这会导致稍后在可执行文件中使用共享对象时链接失败。
如果您使用-O1
或更高版本进行编译,问题就会消失(构造函数是内联的)。
中的显式模板实例化似乎t.cpp
被 中的非隐式声明所禁止t.hpp
。我想出的一种解决方法是#define SOMETHING
在t.cpp
之前#include "t.hpp"
使用in#ifndef SOMETHING
来保护t.hpp
. 但在版本 6 之前的 GCC 中,这不是必需的,我不确定它是否应该如此。
这是 GCC 6.1 中的错误吗?还是代码错了?
编辑:我发现了这个错误:https ://gcc.gnu.org/bugzilla/show_bug.cgi?id=57728这可能是相关的,但它是针对 GCC 4.8 报告的,而我的问题直到 6.1 才出现。GCC 5.1 vs 4.9 确实引入了一个空默认构造函数,= default
而不是多参数的默认参数,但同样,直到 GCC 6.1 才出现我的问题。