gpt4 book ai didi

c++ - C++ 中一系列模板参数的显式模板实例化

转载 作者:行者123 更新时间:2023-12-03 18:47:51 24 4
gpt4 key购买 nike

显式模板实例化在创建库时非常有用。假设我有一个带有 int 参数的模板:

template <int i> struct S { ... };
要执行显式模板实例化,语法类似于
template struct S<1>;
但是,我只能以这种方式使用一行来实例化一个实例。我想做的是以一种优雅的方式定义一系列模板。例如,考虑无法编译的错误代码:
#define MIN_I 1
#define MAX_I 16
for (int i = MIN_I; i <= MAX_I; i++) // i should be a constant
template struct S<i>;
这样,当MAX_I改变时,修改就很简单了。我能达到这个目标吗?如果可能的话,有没有简单的方法来做这样的事情?谢谢!
此外,这个问题可以推广到更一般的设置。例如,我可以取 1,2,4,8,16,32,64,128,256 或一些预定义的序列。
我创建模板库的原因不好说。简而言之,我将创建一个在 GPU 上运行的 CUDA 库(由 nvcc 编译器编译),并由 gcc 编译的标准 c++ 程序调用。

最佳答案

让我们从观点的轻微转变开始。目标是实例化给定模板的某些实例。请注意,我删除了“显式”这个词——虽然会有显式实例化,但它不必是相关模板。相反,我将显式实例化一个帮助模板,该模板将隐式实例化所需的模板。
帮助模板将使用 parameter pack以容纳任意数量的参数。如果目标是简单地列出数字,这将是相当直截了当的。然而,也希望能够指定最小值和最大值。处理这种情况,我支持 std::integer_sequence 作为模板参数,我将通过部分特化处理。

// Start with a template that will not be defined; we will define only a
// specialization of this.
// The `C` parameter allows this to be applied to more templates than just `S`.
// The other parameters will make more sense for the specialization.
template<template<int> typename C, int ADD, class T> struct force_instantiation_impl;

// Partially specializing the template allows access to the numbers comprising the
// `integer_sequence` parameter.
// The ADD parameter will be added to each number in the sequence (will be helpful later).
template<template<int> typename C, int ADD, int... Ints>
struct force_instantiation_impl<C, ADD, std::integer_sequence<int, Ints...>> {
// Implicitly instantiate the desired templates.
std::tuple<C<ADD + Ints>...> unused;
};
在这里,参数包扩展用于迭代所有所需的模板参数。这在问题的“错误代码”中扮演了赋予循环的角色。当然,我们仍然需要获取给定最小值和最大值的索引。
为方便起见,如果您愿意,我会提供另一层帮助模板,即“界面”层。第一个接口(interface)助手允许仅指定模板、最小值和最大值。实例化这个助手将导致所需的模板被实例化。
// Instantiates C<I> for I ranging from MIN to MAX.
// MAX must be at least as large as MIN.
template<template<int> typename C, int MIN, int MAX>
struct force_instantiation_range {
// Check the assumption.
static_assert(MIN <= MAX);
// Make an integer sequence from 0 to (MAX-MIN) for the template argument.
// When MIN is added to each element, the sequence will go from MIN to MAX.
force_instantiation_impl<C, MIN, std::make_integer_sequence<int, MAX-MIN+1>> unused;
};
另一个接口(interface)助手允许简单地列出所需的参数。在某种程度上,这个助手的目的是隐藏通过支持一系列参数而引入的复杂性。 (如果没有这种支持,这个模板的参数可能是 force_instantiation_impl 的参数。)
// Instantiates C<I> for the given I's.
template<template<int> typename C, int... Ints>
struct force_instantiation_list {
force_instantiation_impl<C, 0, std::integer_sequence<int, Ints...>> unused;
};
就是这样。由于注释的原因,它可能看起来像很多代码,但实际上它相当短。有三个结构模板定义,每个都有一个成员。要使用它,请显式实例化其中一个接口(interface)助手。
// Forgive me, I'm changing the pre-processor directives to type-safe constants.
constexpr int MIN_I = 1;
constexpr int MAX_I = 16;
template struct force_instantiation_range<S, MIN_I, MAX_I>;
等效地,可以显式列出参数。
template struct force_instantiation_list<S, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16>;

诚然,我确实改变了这个问题。如果您确实需要直接对模板进行显式实例化,那么这种方法将不起作用。如果是这种情况,您可能不得不依赖预处理器,这可能是一场噩梦。幸运的是, Boost.Preprocessor已经处理了最痛苦的细节。我会利用这一点。

关于c++ - C++ 中一系列模板参数的显式模板实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67513570/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com