问题标签 [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.

0 投票
1 回答
716 浏览

c++ - 了解 declval 优化实现

查看 libstdc++ 源代码,我发现了以下declval实现:

这个实现由 Eric Niebler 作为编译时优化提出的:他解释说重载解析比模板实例化更快。

但是,我无法理解它是如何工作的。具体来说:

  1. 在(1)中,为什么使用_Up比仅仅返回更好_Tp&&
  2. 似乎从未使用过重载(2)。为什么需要它?

这一切如何防止模板实例化,而不是最天真的实现:

0 投票
1 回答
214 浏览

c++ - “if constexpr(something false)”是否总是省略模板实例化

这个模板函数f<X>()是否总是不被实例化?

下面是我的测试(coliru MCVE)。
我创建fun<S>()了它将实例化E<S>当且仅当S!=void.
然后我打电话给fun<void>(),fun<int>()fun<float>()

我相信强制 C++ 编译器if constexpr(false)跳过#1. 我的应该只有2次。 fun<void>()
countRunner++

因此,如果我的假设是正确的,那么下面的程序将始终在每个编译器和每个设置中打印 2。

(它为我打印了 2,但仅凭实验证明什么。)

我可以E<void>相信永远不会被实例化吗?
请提供一些(半)官方参考,让我冷静下来。

编辑:我刚刚发现http://eel.is/c++draft/stmt.if#2C++17 中的“If constexpr”在非模板函数中不起作用

如果if语句的形式为if constexpr,则条件的值应为 bool 类型的上下文转换的常量表达式;这种形式称为constexpr if语句。如果转换条件的值为假,则第一个子语句是丢弃的语句,否则第二个子语句(如果存在)是丢弃的语句。在封闭模板化实体的实例化过程中,如果条件在其实例化后不依赖于值,则丢弃的子语句(如果有)不会被 实例化。[ 注意:废弃语句中的 Odr 使用不需要定义实体。— 尾注]案例默认值出现在这种if语句中的标签应与同一if语句中的 switch 语句相关联。在 constexpr if 语句的子语句中声明的标签只能由同一子语句中的语句引用。

我仍然不确定规则中的“实例化”一词。它与“模板实例化”中的含义相同吗?

0 投票
1 回答
120 浏览

c++ - 实现 pimpl 友好的 unique_ptr

众所周知,它std::unique_ptr可能不方便用于实现 pimpl 习惯用法:可能不会在头文件中默认析构函数和移动运算符(例如,具有不完整类型的 std::unique_ptr 不会编译)。有些人建议改用,因为它使用了一些带有析构函数的技巧来克服它(可能只是类型擦除,但我不确定)。std::shared_ptr

我试图为这种情况创建一个特殊的智能指针,这是实现:

或者,可以用类型擦除替换指向函数的指针,尽管我认为它的效率会降低。

有用:

我看到的唯一缺点是涉及的额外开销很小:还必须存储指向“析构函数”的指针。

我认为这不是什么大问题,因为 8 字节的开销在 pimpl 用例中是微不足道的,我的问题很有趣:是否有一些实用的技巧来消除由dest_caller_?

我可以考虑拆分PimplPtr为声明pimpl.hpp和定义pimpl_impl.hpp,并显式实例化template PimplPtr<PimplMe::Impl>::Reset()in impl.cpp,但我认为它很难看。

声明dest_caller_为静态成员不是一个解决方案,至少因为它需要在多线程情况下进行同步。

0 投票
1 回答
67 浏览

c++ - 使用 `using` 或其他方式显式实例化函数模板

using类模板就像一个魅力

但似乎它根本不适用于功能

那么如何sum5d作为一个专门的/实例化的别名sumNT<double,5>呢?

0 投票
1 回答
116 浏览

c++ - 通过 typedef 模板强制模板实例化- 为什么有效?

我正在学习强制模板实例化。
它有效,但我仍然很好奇:-

它打印 1,因为InitCRTP<WantInit>::init已正确实例化。

观察

  1. 如果我删除该行#2#,它将打印 0。(InitCRTP<WantInit>::init未实例化)。
  2. 如果我#2#从更改int&int,我将得到:-

    错误:'InitCRTP::init' 的值在常量表达式中不可用

  3. 如果我改变#1#totemplate <T>struct NonTypeParameter { };#2#topublic: using dummy=NonTypeParameter<init>;我会得到:-

    错误:“T”尚未声明

问题

  1. 为什么这条线#2#足以强制实例化?
    在我看来,它只是模板类中的一个 typedef,任何人都无法访问。

  2. 为什么我需要int&作为另一个模板参数才能使其可编译?
    一个可能更正确的问题:该技术的名称是什么?

原始帖子:使用 CRTP 强制显式模板实例化

0 投票
4 回答
404 浏览

c++ - 通过 typedef 强制模板实例化:g++ 成功,Visual C++ 失败

我想强制模板实例化。
以下代码1在 g++ ( http://coliru.stacked-crooked.com/a/33986d0e0d320ad4 ) 上工作 (打印)。
但是,它会0在 Visual C++ ( https://rextester.com/WGQG68063 ) 上打印错误的结果 ( )。

它是 Visual C++ 编译器错误,还是一种未定义的行为?
如果是 Visual C++ 错误,如何解决它(同时仍然保持美观)?

编辑:按照 Max Langhof(和许多人)的建议更改类 -> 结构。感谢。

赏金原因

StoryTellerMaxim Egorushkin的相反解决方案以及他们的深入讨论(谢谢!),这听起来像是 C++ 规则的模糊区域。

如果是 Visual C++ 错误,我希望问题能够确定地报告。

此外,我仍然希望有一个很好的解决方法,因为这种技术对于自定义类型 ID 生成非常有用。显式实例化不是那么方便。

注意:我将赏金授予Kaenbyo Rin,因为对我来说,这很容易理解。
这并不意味着其余的答案不太正确或不太有用。
我仍然不确定哪个是正确的。读者应谨慎行事。
为了安全起见,我假设我只是不能使用该功能(目前)。感谢大家。

0 投票
1 回答
57 浏览

c++ - 此类模板的对象创建如何工作?

我在下面有这段代码,我正在尝试我正在学习的课程,这几乎可以做到预期做的事情

但我不明白下面的部分是如何工作的。我了解模板的默认参数部分如何工作,但不了解模板类实例化后代码如何创建对象。

为什么不像第一种情况那样创建显式对象A<char> a('A', 'A');?我没有看到使用g++ -Wall -Wextra --std=c++11. 此外,如果 cppreference 中解释此行为的特定子句将不胜感激,因为我错过了确定在哪里解释了这种行为。

0 投票
0 回答
63 浏览

c++ - 模板实例化期间的 gcc 编译错误

我目前正在从 gcc 4.9 (c++1) 升级到 gcc 8.2 (c++14),我在 gcc 8.2 上遇到问题,代码如下

错误如下:

你可以在这里找到代码和错误

我还发现,如果我删除 E00 = std::decay_t 并像这样替换每个 E 的 E00 :

代码正在编译,但我不明白为什么。

你知道为什么它不在 gcc 8.2 上编译而是在 gcc 4.9 上吗?

0 投票
2 回答
71 浏览

c++ - 是否有显式实例化深度模板类的技巧?

我有个问题:

我想明确地实例化一个类Datatype,如:

对于显式实例化,我需要使用详细的类型说明符。其中不允许使用 typedef。因此我不能写:

但我必须写:

如果那里还剩下任何 typedef,我也必须替换它们,这可能会导致类似:

如您所见,这变得非常不清楚。

有什么技巧可以避免所有类型定义的解构吗?

如果在使用时也可以使用技巧,那将是最好的extern template

0 投票
1 回答
82 浏览

c++ - dllexport 类模板实例(专业化),减少仅头文件模板库的编译时间

是否可以导出一些类模板实例,同时让库的用户能够生成给定类模板的其他特化(编译可执行文件时)。

鉴于我有一个公共标头

通过这种声明类模板的方式,Foo每个实例化都将发生在用户的可执行文件中。

但是,如果我定义Foodllexport/dllimport使用API宏,则其每个Foo特化都没有在 dll 中显式实例化,将无法链接。

那么,是否可以强制编译器在导出一个类模板实例时链接到现有的类模板实例,并生成另一个没有的类模板实例。

更新

我找到了解决方案,请参阅下面的答案。我留下旧的更新,以防有人会发现 SFINAE 的这种用法有帮助。


更新旧

我发现了一个涉及 SFINAE 的繁琐解决方案,但它导致定义一个类模板两次,因此非常容易出错。我不知道它是否可以用宏包裹起来,这样就可以只写一次。