Search code examples
c++classtemplatesclass-template

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


Say you have a class template (e.g. second below). Say that class template's template arguments are instantiations of another class template (e.g. first below). How do you access the template argument's own template arguments? Is that possible?

Here's some code:

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;
}

Three possibilities come to mind:

  1. rewrite first to store n as a data member, or
  2. redesign second to inherit from an instantiated class from first, and
  3. ask for the exact same template arguments in both class templates.

I ask because I would rather not edit pre-existing code (option 1), and in my particular application, it doesn't really make sense (to me, at least) to think of second as being a type of first (option 2). I will be instantiating many objects of type specialized_first, and so it makes more sense for second to "own" these objects and store them in a container. Option 3 doesn't seem very stylish, either.

Are there any fancy template features that I don't know about to accomplish this in a nice way?


Solution

  • The more sensible way is not to store n as a data member but rather as static constexpr size_t so it doesn't allocate any additional runtime space. This is the standard and most flexible mechanism - allowing for various other templates to access this parameter without mush fuss. E.g., you can make a completely different version of first and allow your second to utilize the other version all the while supporting the original as long as all version satisfy the concept interface.

    Similarly, every typename T_ template parameter can be forwarded to users of the template via using T = T_;. In general, template parameters are inaccessible unless you allow them to be by declaring them to be types or storing their value as constexpr or otherwise.

    You can remodel second so it accepts the same template parameter but it becomes harder the more other templates you have that use first and this value/type or when you suddenly want to use second for an alternative version of first. Better address such problems on the root. For example, in std all their template classes have all the necessary types declared inside the class in a similar manner.