问题标签 [explicit-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 回答
363 浏览

c++ - MSVC 无法编译带有私有​​类型作为参数的显式模板实例化

考虑以下示例,由 4 个文件组成。



外层.h


通用算法.h


通用算法.cpp


主文件


如您所见,argument 有一个函数模板genericAlgorithm.cpp的显式实例化,它是 class 的私有内部结构。genericAlgorithm()Outer::InnerOuter

我的理解是这是合法的,因为根据cppreference.com ...

显式实例化定义忽略成员访问说明符:参数类型和返回类型可能是私有的。

事实上,这段代码在 GCC 6.3 和 Clang 4.0 上编译得非常好。

但是,MSVC (Visual Studio 2017 15.2)似乎对此有异议并产生以下编译错误:


那么,这是 MSVC 中的错误,还是我遗漏了什么,实际上我的代码有问题需要修复?如果是这样,是否意味着 GCC 和 Clang 以及 cppreference.com 错了?


更新:我相信我在标准的n4296n4567工作草案的§14.7.2 [templ.explicit](第 12 项)中找到了相关段落:

通常的访问检查规则不适用于用于指定显式实例化的名称。[注意:特别是,函数声明器中使用的模板参数和名称(包括参数类型、返回类型和异常规范)可能是通常无法访问的私有类型或对象,并且模板可能是成员模板或成员函数通常无法访问。——尾注]

除非我误解了所写的内容,否则 MSVC 的这种行为似乎确实不合规。当然,这些只是草稿——不幸的是,我无法获得每份 133 美元的实际标准,因此我无法确定该项目是否已被保留。

0 投票
0 回答
26 浏览

c++ - 显式实例化模板类是否也显式实例化关联的模板友元函数?

我试图重载 ostream << 运算符以打印出泛型类型的变量,但是 main.cpp 找不到实现。我假设这是因为实现存在于 .cpp 文件中。我知道模板函数通常必须在头文件中定义,但是对于显式实例化的函数不应该是这种情况。当我将实现复制到我的头文件中时,它工作得很好。

我在想我遇到了模板化朋友功能独有的问题。这是我的代码的相关部分。

我转发声明了我的 Node 类和运算符重载

我在头文件 (Tree.h) 中声明了运算符重载

在我的 .cpp 文件中,我实现了它

我在 Tree.cpp 文件的底部显式实例化了我的节点

然后最后我从 main.cpp 调用它

我收到以下错误:

0 投票
3 回答
582 浏览

c++ - 模板链接器错误的显式实例化

我正在寻求您的帮助,因为我正在使用模板,而且似乎我误解了一些东西。

这是我的代码:

arbre.h

arbre.tpp

main.cpp包含“ arbre.h”并创建一个像这样的对象:

所以按照这篇关于显式实例化的文章:http ://www.cplusplus.com/forum/articles/14272/

我在 arbre.tpp 的末尾添加了这两行:

这样链接器就可以在 arbre.o 中为我的对象的 int 版本编译代码,这样我就可以将实现 (arbre.tpp) 与标头 (arbre.h) 分开。我的代码使用隐式实例化(arbre.tpp 包含在 header.h 的末尾),但我想将它们分开。

我想知道为什么链接失败:

你有什么主意吗 ?我正在做与我链接的文章中相同的事情,不是吗?

提前致谢。

0 投票
1 回答
41 浏览

c++ - boost multi_index 容器的显式实例化

首先我想展示工作代码,然后解释我想如何改变事情。这是简单的 boost multi_index 示例:

想象一下如果 main.cpp 是另一个没有 boost 依赖的模块。我想了解如何:

包括一些头文件,其中 boost multiindex 容器类被前向声明到 main.cpp 在附加的 .cpp 文件中定义员工的多索引容器我尝试了很多变体,但如果这可行,则没有。有可能创造出这样的东西吗?

现在是 h.file 我需要填写容器的前向声明(或显式启动)。我可能会误解这些术语,但我是 C++ 和 boost 的新手。

这是最终目标。我想提醒一下 main.cpp 被想象为另一个模块的 .cpp ,没有提升依赖。

0 投票
1 回答
275 浏览

c++11 - 外部模板类向量> 替代品

这开始是一个问题:“为什么不能显式实例化 std::unique_ptr 的 std::vector?” 如:

template class std::vector<std::unique_ptr<int>>;

尽管以下显式实例化和变量很好:

但问题变成了:“有什么替代方案?”

我将发布我的演练来回答这两个问题,因为我没有找到一个感觉足够相似的问题。我也在寻找替代品,如果有的话。

0 投票
1 回答
163 浏览

c++ - 使用 auto->decltype 方法显式实例化函数

我想创建能够提取结构 A 的任何属性的模板函数。

这是 Source.h

现在我想对 foo 使用显式实例化方法

Source.cpp来了:

如果我们查看 Main.cpp,我们可以看到,如果在上面的代码块中没有显式实例化,我们会得到链接错误:

现在我的问题是如何为 &A::b 和 &A::c 类型显式实例化 foo 。我尝试了很多变种,但没有任何效果。我在视觉工作室 2015。

PS哦,还有一个。我们可以用默认参数为 foo 制作 foo R = decltype(&A::b)吗?

0 投票
2 回答
1099 浏览

c++ - 有条件地删除模板类中的方法

背景:由于模板代码膨胀,STL 的使用使构建速度变慢:通常相同的方法在许多不同的翻译单元中独立实例化,并被多次编译和优化。避免模​​板类的这种对象代码重复的一种方法是使用显式模板实例化外部模板声明,但 STL 实现不支持它们。我正在尝试实现一个std::vector<T>支持显式实例化的等价物。


问题:我有一个模板类,如果模板参数不满足某些条件vector<T>,我希望删除它的一些方法。T更糟糕的是,这里有一些额外的要求:

  1. vector<T>无论是否T满足条件,都必须可以显式实例化。
  2. 当有人调用有条件删除的方法时,应该会发出编译错误。
  3. 我有几个这样的条件,以及一组依赖于每个条件的方法。

讨论:例如,该方法在不可复制vector<T>::push_back(const T&)时无法工作。T

如果我保持这个方法实现不变,那么如果我显式实例化 eg ,编译器将产生错误vector<unique_ptr<int>>,因为它将无法复制unique_ptr<int>. 这与要求 1 相矛盾,并使所需的代码膨胀优化变得不可能。

我可以对 进行两种不同的实现vector<T>::push_back(const T&),一种用于可复制构造的类型,另一种用于其他类型。这可以使用 SFINAE 重载或使用辅助模板类来完成。非复制构造案例的实现可以简单地抛出异常或调用终止。但是随后调用 for 的方法push_back只会vector<unique_ptr<int>>在运行时崩溃。如要求 2 所述,它不会产生编译错误。

最后,有几个条件,每个条件都排除了一些方法。该类型T可以在各种组合中缺少以下属性:可复制构造、可复制赋值、可默认构造、可移动构造。相关问题的解决方案似乎仅适用于一种条件,不满足要求 3。

我剩下的唯一想法是使用某种整体的部分专业化vector<T>与预处理器技巧相结合。但这需要像 16 个独立的专业,这听起来很糟糕。

PS很明显,STL 设计本质上依赖于隐式实例化的机制,这使得减少由它们引起的代码膨胀变得非常困难。

0 投票
4 回答
502 浏览

c++ - 如何简洁地编写大量显式函数模板实例化?

我正在编写一个 C++ 库,其中包含许多我想显式实例化和导出多个类型参数的函数模板。在我的特殊情况下,我有很多数字函数模板,我想分别为floatdoublelong double. 它们看起来像这样:

如果我有 M 个函数模板和 N 个基础类型,那么我就有 M*N 个显式实例化要输入。是否可以更简洁地编写这些实例化?

我当前的解决方案是使用一个预处理器宏来执行给定类型的所有实例化:

然而,这是次优的,因为它需要我单独维护每个函数模板签名的另一个副本。此外,如果我想在多个翻译单元中执行此操作,那么我需要在每个翻译单元中单独维护一个基础类型列表。(假设 C++2a 添加了long long double我想要支持的类型;我必须添加EXPLICITLY_INSTANTIATE(long long double);到每个文件中。)

另一种可能的方法是将我的所有函数收集到一个(仅静态)模板类中:

这解决了第一个问题,即分别维护每个签名的两个副本,但需要我将每个调用更改为calculate_ainto calculate::a<T>。它没有解决第二个问题。

0 投票
1 回答
598 浏览

c++ - 在显式实例化期间,不完整类型何时可以使用?

我正在尝试制作一种自动创建包装对象的包装类:

此外,我希望能够向(对于PIMPL 模式)的T用户隐藏实现细节。对于单翻译单元示例,假设我有Foo<T>

这一切都很好。但是,如果我想要求T从另一个类派生,编译器会抱怨Bar不完整:

尝试使用相同的检查static_cast同样失败:

但是,似乎如果我添加另一个级别的函数模板,我可以做到这一点:

请注意,尽管结构相似,但即使以下内容仍会导致不完整类型错误:

这里发生了什么?附加功能是否会以某种方式延迟对 static_assert 的检查?是否有更清洁的解决方案,不涉及添加功能,但仍允许template class Foo<Bar>;在定义之前放置Bar

0 投票
0 回答
56 浏览

c++ - 显式模板类实例化不包括编译器生成的成员函数的符号?

如果我显式实例化具有默认析构函数、默认移动构造函数等的模板类,并且从不在该翻译单元中使用该类型,则它不包括编译器生成的成员函数。

例如,如果模板类array2d具有编译器生成的成员函数,例如:

如果我像这样明确地实例化它:

并将其编译为array.cc.o我得到这些符号:

编译器生成的成员函数的符号都不存在。

为什么显式模板类实例化不创建这些符号?