如何访问模板参数自己的模板参数?

How to access the template argument's own template arguments?

假设您有一个 class 模板(例如下面的 second)。假设 class 模板的模板参数是另一个 class 模板的实例(例如下面的 first)。你如何访问模板参数自己的模板参数?这可能吗?

这是一些代码:

template<size_t n>
class first {
};

template<typename instantiated_first>
class second {
    // would like to be able to access the "n"
    // of instantiated_first
};

int main() {
    second<first<3>> thing;

    return 0;
}

想到三种可能性:

  1. 重写 first 以将 n 存储为数据成员,或
  2. 重新设计 second 以继承 first 的实例化 class,以及
  3. 在两个 class 模板中要求完全相同的模板参数。

我问是因为我不想编辑预先存在的代码(选项 1),并且在我的特定应用程序中,(至少对我而言)考虑 second 真的没有意义作为 first 的一种类型(选项 2)。我将实例化许多 specialized_first 类型的对象,因此 second 到 "own" 这些对象并将它们存储在容器中更有意义。方案3好像也不太时髦

是否有任何我不知道的精美模板功能可以很好地完成此任务?

您声明一个偏特化并从那里选择参数。

template<typename T>
class second<first<T>> {
    // T is available here for use.
};

或者更普遍地这样做

template<typename T, typename U
class second<U<T>> {
    // T is available here for use.
};

这将匹配具有一个模板参数的所有实例化。

更明智的方法是不将 n 存储为数据成员,而是存储为 static constexpr size_t,这样它就不会分配任何额外的运行时 space。这是标准且最灵活的机制 - 允许各种其他模板轻松访问此参数。例如,您可以制作一个完全不同的 first 版本,并允许您的 second 在支持原始版本的同时一直使用其他版本,只要所有版本都满足概念接口即可。

同样,每个typename T_模板参数都可以通过using T = T_;转发给模板的用户。通常,模板参数是不可访问的,除非您通过将它们声明为类型或将它们的值存储为 constexpr 或其他方式来允许它们。

您可以改造 second 使其接受相同的模板参数,但是使用 first 和此 value/type 的其他模板越多,或者当您突然想要使用 second 作为 first 的替代版本。更好地从根本上解决此类问题。例如,在 std 中,他们所有的模板 classes 都以类似的方式在 class 中声明了所有必要的类型。