This is not a major code breaking issue, I'm just wondering if I'm missing some neat trick.
If I am writing a templated class, I may start like this:
// some_header.h
template <typename TypeParameter, size_t max_array_size>
class TemplatedClass
{
std::array<TypeParameter, max_array_size> MyTemplatedArray;
public:
TypeParameter do_something()
{
/* do something with TypeParameter and max_array_sizein here */
}
}
This is fine, but when I have less trivial templated examples, I tend to separate out the function definitions from the declarations, like so:
// some_header.h
template <typename TypeParameter, size_t max_array_size>
class TemplatedClass
{
std::array<TypeParameter, max_array_size> MyTemplatedArray;
public:
TypeParameter do_something();
/*
Many more function declarations
*/
}
template <typename TypeParameter, size_t max_array_size>
TemplatedClass<TypeParameter, max_array_size>::do_something()
{
/* do something with TypeParameter and max_array_sizein here */
}
/*
Many more function definitions, all with:
template <typename TypeParameter, size_t max_array_size>
TemplatedClass<TypeParameter, max_array_size>
at the start
*/
The aim of this would be to have a classic skeleton class definition that can easily be read by others at a glance. I don't mind doing this, but the annoying thing is when I want to modify the template parameters. What is one change in the first example, ends up being 1 + 2 * n changes in the second example!
So what I am wanting to know is: Is there a way to make the second example's template parameters more maintainable? Maybe something similar to a typedef/using or maybe some keyword I haven't heard of?
First a non-answer:
Suppose, /*do something*/ depends on the template parameters. In that case, having to fix the signature is the smaller issue. You need to fix the implementation.
The other case is that /*do something*/ does not depend on the template parameters. Then you can move the methods to a non template base class.
A more serious attempt to answer the question:
What if TemplatedClass would have only a single template parameter instead of many? Instead of using a bunch of template parameters for TemplatedClass you can use a single tag and definition of the actual parameters can be defered to traits:
#include <array>
template <typename Tag> struct value_type_impl;
template <typename Tag> using value_type = typename value_type_impl<Tag>::type;
template <typename Tag> constexpr int array_size = 123;
template <typename Tag>
class TemplatedClass {
std::array<value_type<Tag>, array_size<Tag> > MyTemplatedArray;
public:
value_type<Tag> do_something();
};
template <typename Tag>
value_type<Tag> TemplatedClass<Tag>::do_something() {
return {};
}
// the tag
struct foo_tag{};
// specializations for foo_tag:
template <> struct value_type_impl<foo_tag> { using type = int; };
template <> constexpr int array_size<foo_tag> = 123;
int main() {
TemplatedClass<foo_tag> tc;
}
Now the burdon is on the user of the template to define one tag and then specialize the required traits for that tag. Though, the method definition has only a single template parameter that does not need to change when more "parameters" (traits) are added or removed. Of course you still need to fix the implementation.
If you were looking merely for some syntactic sugar, I am not aware of something that would help without changing the template itself.
Related
I have a class that can either be constructed by arguments of "ordinary" types, int, string, etc., or that can be constructed by a couple of different 'special' types invented by a coworker.
The 'special' types have the same signature, but aren't in a parent-child relationship.
So the code I have now looks something like:
class my_nifty_class {
public:
// "ordinary" constructor
template <class T> my_nifty_class(T) {some generic code}
// "special" constructors
my_nifty_class(my_first_clever_class) {
some clever code
}
my_nifty_class(my_second_clever_class) {
the identical clever code
}
In order to avoid duplicating some clever code (and opening myself up to the risk of not always duplicating it right), I would like to replace this with
class my_nifty_class {
public:
// "ordinary" constructor
template <class T> my_nifty_class(T) {some generic code}
// "special" constructors
template <class clever_class> my_nifty_class(clever_class) {
/**** I need template magic somewhere around here ****/
some clever code
}
But -- I don't know the template magic to put in there, or if there is any such magic to be had. I know I could do it if I were declaring classes -- but I'm declaring functions, so I'm kinda stuck.
You want std::enable_if, and you want some compile-time property of your special classes that other classes don't have.
template <class T, class S = std::enable_if_t<!is_my_special_v<T>>>
my_nifty_class(T) {some generic code}
template <class T, class S = std::enable_if_t<is_my_special_v<T>>, bool = true>
my_nifty_class(T) {some special code}
(The dummy template parameter is needed to make the two templates distinct)
Another method is to have just one constructor and use the special selector inside.
template <class T>
my_nifty_class(T) {
if constexpr(is_my_special_v<T>)
some special code
else
some generic code
}
How do you write is_my_special_v? It is just a template with the value of false, with specialisations for your special types with the value of true.
template<class> constexpr bool is_my_special_v = false;
template<> constexpr bool is_my_special_v<MySpecialType1> = true:
// ...
If all your special classes have some member name that is unlikely to occur in non-special classes, you can use that in order to write just one specialisation of is_my_special_v total instead of one per special class. Search for "c++ member detection", lots of material out there.
Finally, if this is the only place where your special types are indeed special, you can skip
is_my_special_v altogether and just check directly.
template <class T>
my_nifty_class(T) {
if constexpr(std::is_same_v<T, MySpecialType1> ||
std::is_same_v<T, MySpecialType2> ...)
some special code
else
some generic code
}
Here is my go at the answer. You will just share a generic constructor for all types. And handle the logic within the constructor using std::is_pod which was introduced in c++11 I believe.
Essentially POD (plain old data) types such as; int, float, double, etc. will be handled by one templated function, and any complex/non-trivial data types will be handled by your other templated function.
class my_nifty_class {
public:
template<class T> handle_pod_type(T value)
{ /* Code to handle POD data types */ }
template<class SpecialType> handle_special_type(SpecialType value)
{ /* Code to handle complex data types */ }
template <class T> my_nifty_class(T value) {
if( std::is_pod<T>::value ) {
handle_pod_type(value);
}
else {
handle_special_type(value);
}
}
}
Also take note of what is_pod is doing and what classifies a POD type in C++11.
I suggest that you can use "tag structures" and class template specializations to solve your problem:
struct TypeA {};
struct TypeB {};
struct TypeC {};
class Class {
public:
template<class T> Class(T val) : Class(typename SelectTag<T>::Type{}, val) {}
private:
struct GenericTag {};
struct BOrCTag {};
template<class T> struct SelectTag { using Type = GenericTag; };
template<class T> Class(GenericTag, T val) { /* do smth */ }
template<class T> Class(BOrCTag, T val) { /* do smth else */ }
};
template<> struct Class::SelectTag<TypeB> { using Type = BOrCTag; };
template<> struct Class::SelectTag<TypeC> { using Type = BOrCTag; };
I wondered if there was any advantages of declaring templates function out of line vs in the class.
I'm trying to get a clear understanding of the pros and cons of the two syntax.
Here's an example:
Out of line:
template<typename T>
struct MyType {
template<typename... Args>
void test(Args...) const;
};
template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
// do things
}
Vs in class:
template<typename T>
struct MyType {
template<typename... Args>
void test(Args... args) const {
// do things
}
};
Are there language features that are easier to use with the first or second version? Does the first version would get in the way when using default template arguments or enable_if? I would like to see comparisons of how those two cases are playing with different language features like sfinae, and maybe potential future features (modules?).
Taking compiler specific behavior into account can be interesting too. I think MSVC needs inline in some places with the first code snippet, but I'm not sure.
EDIT: I know there is no difference on how these features works, that this is mostly a matter of taste. I want to see how both syntaxes plays with different techniques, and the advantage of one over the other. I see mostly answers that favors one over another, but I really want to get both sides. A more objective answer would be better.
There is no difference between the two versions regarding default template arguments, SFINAE or std::enable_if as overload resolution and substitution of template arguments work the same way for both of them. I also don't see any reason why there should be a difference with modules, as they don't change the fact that the compiler needs to see the full definition of the member functions anyway.
Readability
One major advantage of the out-of-line version is readability. You can just declare and document the member functions and even move the definitions to a separate file that is included in the end. This makes it so that the reader of your class template doesn't have to skip over a potentially large number of implementation details and can just read the summary.
For your particular example you could have the definitions
template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
// do things
}
in a file called MyType_impl.h and then have the file MyType.h contain just the declaration
template<typename T>
struct MyType {
template<typename... Args>
void test(Args...) const;
};
#include "MyType_impl.h"
If MyType.h contains enough documentation of the functions of MyType most of the time users of that class don't need to look into the definitions in MyType_impl.h.
Expressiveness
But it is not just increased readibility that differentiates out-of-line and in-class definitions. While every in-class definition can easily be moved to an out-of-line definition, the converse isn't true. I.e. out-of-line definitions are more expressive that in-class definitions. This happens when you have tightly coupled classes that rely on the functionality of each other so that a forward declaration doesn't suffice.
One such case is e.g. the command pattern if you want it to support chaining of commands and have it support user defined-functions and functors without them having to inherit from some base class. So such a Command is essentially an "improved" version of std::function.
This means that the Command class needs some form of type erasure which I'll omit here, but I can add it if someone really would like me to include it.
template <typename T, typename R> // T is the input type, R is the return type
class Command {
public:
template <typename U>
Command(U const&); // type erasing constructor, SFINAE omitted here
Command(Command<T, R> const&) // copy constructor that makes a deep copy of the unique_ptr
template <typename U>
Command<T, U> then(Command<R, U> next); // chaining two commands
R operator()(T const&); // function call operator to execute command
private:
class concept_t; // abstract type erasure class, omitted
template <typename U>
class model_t : public concept_t; // concrete type erasure class for type U, omitted
std::unique_ptr<concept_t> _impl;
};
So how would you implement .then? The easiest way is to have a helper class that stores the original Command and the Command to execute after that and just calls both of their call operators in sequence:
template <typename T, typename R, typename U>
class CommandThenHelper {
public:
CommandThenHelper(Command<T,R>, Command<R,U>);
U operator() (T const& val) {
return _snd(_fst(val));
}
private:
Command<T, R> _fst;
Command<R, U> _snd;
};
Note that Command cannot be an incomplete type at the point of this definition, as the compiler needs to know that Command<T,R> and Command<R, U> implement a call operator as well as their size, so a forward declaration is not sufficient here. Even if you were to store the member commands by pointer, for the definition of operator() you absolutely need the full declaration of Command.
With this helper we can implement Command<T,R>::then:
template <typename T, R>
template <typename U>
Command<T, U> Command<T,R>::then(Command<R, U> next) {
// this will implicitly invoke the type erasure constructor of Command<T, U>
return CommandNextHelper<T, R, U>(*this, next);
}
Again, note that this doesn't work if CommandNextHelper is only forward declared because the compiler needs to know the declaration of the constructor for CommandNextHelper. Since we already know that the class declaration of Command has to come before the declaration of CommandNextHelper, this means you simply cannot define the .then function in-class. The definition of it has to come after the declaration of CommandNextHelper.
I know that this is not a simple example, but I couldn't think of a simpler one because that issue mostly comes up when you absolutely have to define some operator as a class member. This applies mostly to operator() and operator[] in expession templates since these operators cannot be defined as non-members.
Conclusion
So to conclude: It is mostly a matter of taste which one you prefer, as there isn't much of a difference between the two. Only if you have circular dependencies among classes you can't use in-class defintion for all of the member functions. I personally prefer out-of-line definitions anyway, since the trick to outsource the function declarations can also help with documentation generating tools such as doxygen, which will then only create documentation for the actual class and not for additional helpers that are defined and declared in another file.
Edit
If I understand your edit to the original question correctly, you'd like to see how general SFINAE, std::enable_if and default template parameters looks like for both of the variants. The declarations look exactly the same, only for the definitions you have to drop default parameters if there are any.
Default template parameters
template <typename T = int>
class A {
template <typename U = void*>
void someFunction(U val) {
// do something
}
};
vs
template <typename T = int>
class A {
template <typename U = void*>
void someFunction(U val);
};
template <typename T>
template <typename U>
void A<T>::someFunction(U val) {
// do something
}
enable_if in default template parameter
template <typename T>
class A {
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
bool someFunction(U const& val) {
// do some stuff here
}
};
vs
template <typename T>
class A {
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
bool someFunction(U const& val);
};
template <typename T>
template <typename U, typename> // note the missing default here
bool A<T>::someFunction(U const& val) {
// do some stuff here
}
enable_if as non-type template parameter
template <typename T>
class A {
template <typename U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
bool someFunction(U const& val) {
// do some stuff here
}
};
vs
template <typename T>
class A {
template <typename U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
bool someFunction(U const& val);
};
template <typename T>
template <typename U, std::enable_if_t<std::is_convertible<U, T>::value, int>>
bool A<T>::someFunction(U const& val) {
// do some stuff here
}
Again, it is just missing the default parameter 0.
SFINAE in return type
template <typename T>
class A {
template <typename U>
decltype(foo(std::declval<U>())) someFunction(U val) {
// do something
}
template <typename U>
decltype(bar(std::declval<U>())) someFunction(U val) {
// do something else
}
};
vs
template <typename T>
class A {
template <typename U>
decltype(foo(std::declval<U>())) someFunction(U val);
template <typename U>
decltype(bar(std::declval<U>())) someFunction(U val);
};
template <typename T>
template <typename U>
decltype(foo(std::declval<U>())) A<T>::someFunction(U val) {
// do something
}
template <typename T>
template <typename U>
decltype(bar(std::declval<U>())) A<T>::someFunction(U val) {
// do something else
}
This time, since there are no default parameters, both declaration and definition actually look the same.
Are there language features that are easier to use with the first or second version?
Quite trivial a case, but it's worth to be mentioned: specializations.
As an example, you can do this with out-of-line definition:
template<typename T>
struct MyType {
template<typename... Args>
void test(Args...) const;
// Some other functions...
};
template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
// do things
}
// Out-of-line definition for all the other functions...
template<>
template<typename... Args>
void MyType<int>::test(Args... args) const {
// do slightly different things in test
// and in test only for MyType<int>
}
If you want to do the same with in-class definitions only, you have to duplicate the code for all the other functions of MyType (supposing test is the only function you want to specialize, of course).
As an example:
template<>
struct MyType<int> {
template<typename... Args>
void test(Args...) const {
// Specialized function
}
// Copy-and-paste of all the other functions...
};
Of course, you can still mix in-class and out-of-line definitions to do that and you have the same amount of code of the full out-of-line version.
Anyway I assumed you are oriented towards full in-class and full out-of-line solutions, thus mixed ones are not viable.
Another thing that you can do with out-of-line class definitions and you cannot do with in-class definitions at all is function template specializations.
Of course, you can put the primary definition in-class, but all the specializations must be put out-of-line.
In this case, the answer to the above mentioned question is: there exist even features of the language that you cannot use with one of the version.
As an example, consider the following code:
struct S {
template<typename>
void f();
};
template<>
void S::f<int>() {}
int main() {
S s;
s.f<int>();
}
Suppose the designer of the class wants to provide an implementation for f only for a few specific types.
He simply can't do that with in-class definitions.
Finally, out-of-line definitions help to break circular dependencies.
This has been already mentioned in most of the other answers and it doesn't worth it to give another example.
Separating the declaration from the implementation allows you to do this:
// file bar.h
// headers required by declaration
#include "foo.h"
// template declaration
template<class T> void bar(foo);
// headers required by the definition
#include "baz.h"
// template definition
template<class T> void bar(foo) {
baz();
// ...
}
Now, what would make this useful? Well, the header baz.h may now include bar.h and depend on bar and other declarations, even though the implementation of bar depends on baz.h.
If the function template was defined inline, it would have to include baz.h before declaring bar, and if baz.h depends on bar, then you'd have a circular dependency.
Besides resolving circular dependencies, defining functions (whether template or not) out-of-line, leaves the declarations in a form that works effectively as a table of contents, which is easier for programmers to read than declarations sprinkled across a header full of definitions. This advantage diminishes when you use specialized programming tools that provide a structured overview of the header.
I tend to always merge them - but you can't do that if they are codependent. For regular code you usually put the code in a .cpp file, but for templates that whole concept doesn't really apply (and makes for repeated function prototypes). Example:
template <typename T>
struct A {
B<T>* b;
void f() { b->Check<T>(); }
};
template <typename T>
struct B {
A<T>* a;
void g() { a->f(); }
};
Of course this is a contrived example but replace the functions with something else. These two classes require each other to be defined before they can be used. If you use a forward declaration of the template class, you still cannot include the function implementation for one of them. That's a great reason to put them out of line, which 100% fixes this every time.
One alternative is to make one of these an inner class of the other. The inner class can reach out into the outer class beyond its own definition point for functions so the problem is kind of hidden, which is usable in most cases when you have these codependent classes.
I'm trying to create an alias to a template, rather than a type and I can't find the syntax to do it. Below is an example that demonstrates my problem. My guess is this is just something that can't be done, but I'm hoping someone can prove me wrong. If it can't be done, is there some underlying reason it doesn't make sense to do this, or is it just not implemented?
template <class S>
class Down;
template <class S>
class Up {
template <class S1>
using Opposite = Down<S1>;
};
template <class S>
class Down {
template <class S1>
using Opposite = Up<S1>;
};
template <template <typename> class Direction>
void oneDirection() {
//Call another function here that uses the template argument as a template
}
template <template <typename> class Direction>
void bothDirections() {
oneDirection<Direction>();
oneDirection<Direction::Opposite>(); //This doesn't compile
}
int main() {
bothDirections<Up>();
}
In Direction::Opposite, Direction:: is a nested-name-specifier, and it can't indeed denote a class template (you'd need to give it the required template arguments to make it a template specialization).
I suppose one reason to not allow that form is that class templates can have partial or explicit specializations, which can provide different members from the primary template, so the compiler needs to work with a specific specialization to be able to know exactly what's available in there.
You can work around this by using traits to associate the two templates:
template<class> class Up { };
template<class> class Down { };
template<template<class> class Direction> struct Direction_traits;
template<> struct Direction_traits<Up>
{
template<class S1> using Opposite = Down<S1>;
};
template<> struct Direction_traits<Down>
{
template<class S1> using Opposite = Up<S1>;
};
template<template<class> class Direction>
void oneDirection() {
//Do something here
}
template<template<class> class Direction>
void bothDirections() {
oneDirection<Direction>();
oneDirection<Direction_traits<Direction>::template Opposite>();
}
int main() {
bothDirections<Up>();
}
However, keep in mind that Direction_traits<Up>::Opposite is not the same template as Down, at least not yet - the language rules may change in the future, more details in this answer and its comments.
This could cause problems if you want to get back to Up from inside oneDirection<Direction_traits<Up>::Opposite> using the traits - there won't be a trait specialization defined for the alias template. Things would need to get a bit more complicated to allow such use; a possible solution is outlined in the answer quoted above.
So first, apologies for terminology - I'm not sure if template prototype is the correct term. By this I mean :
template <class T, class X>
class TemplatePrototype
{
// code
};
I have a situation where I have a function that creates a template object based upon template arguments to that function.
template <class T, class X>
void doSomething()
{
TemplatePrototype<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
However, there are about 15 different versions of TemplatePrototype, which all have the same interface but different execution (TemplatePrototype is provided by another library). As a result, I have a lot of code that looks like this:
template <class T, class X>
void doSomethingWithOne()
{
TemplatePrototypeOne<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
template <class T, class X>
void doSomethingWithTwo()
{
TemplatePrototypeTwo<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
As a consequence of the architecture, I must know which TemplatePrototype I am going to use before I know the actual types T and X. I would like to see something like this:
template <class T, class X, class Prototype>
void doSomething()
{
Prototype<T, X> aPrototype;
aPrototype.doSomething();
}
But where I have specified part of the template arguments in advance - i.e I specify Prototype before I know T and X. Obviously, this is not possible in C++.
Equally, I cannot pass the Prototype as a template argument because it will still result in huge amounts of duplicate code.
Some important facts : I know the range of all possible inputs.
So I could theoretically use a macro to define each possible template specialisation and insert them into a container, which I would then use to access the specialisation I need. However, I am looking for a more 'elegant' solution - is it possible to pass template prototypes without specialising them as an argument to a template class, and then instantiate later when a function is called? Example:
template <class Prototype>
class Holder
{
template <class T, class X>
void doSomething()
{
Prototype<T, X> aPrototype;
aPrototype.doSomethingElse();
}
};
As far as I know this is impossible, but I was wondering if the SO community had some folks who know a solution?
EDIT:
So I have implemented this as my solution, thanks to the answers below!
#include <iostream>
template <typename T>
struct Foo
{
Foo() { aPtr = 0; }
T* aPtr;
};
template <template<typename> class C>
struct Bar
{
template <class T>
void doSomething()
{
C<T> aClass;
if (aClass.aPtr)
std::cout << "Hello world" << std::endl;
}
};
int main()
{
Bar<Foo> aFoo;
aFoo.doSomething<int>();
return 0;
}
This enables me to specify which TemplatePrototype I wish to use, before I can know the template parameters.
Yes, use a template template parameter, e.g.
template <typename T>
struct Foo
{
};
template <template<typename> class C>
struct Bar
{
};
then
Bar<Foo> b;
You're looking for template template parameters.
In the template parameter list, instead of just:
class TemplatePrototype
specify your prototype as a class template which itself has two template type parameters (without giving them a name here), like:
template<class,class> class TemplatePrototype
//^^^^^^^^^^^^^^^^^^^
This will result in a function like:
template <class T, class X,
template<class,class> class TemplatePrototype>
void doSomething()
{
TemplatePrototype<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
Invocation example:
doSomething<T, X, TemplatePrototypeOne>();
To become independent of the number of template parameters you pass to your "prototype" (here it was 2, namely T and X), you can use variadic templates (since C++11).
For this, first move the prototype template parameter to the first position:
template <template<class,class> class TemplatePrototype,
class T, class X>
Then, replace class T, class X with class ...Ts, which is a placeholder of an arbitrary number of type parameters. Also, in the template template parameter list, replace class,class with class.... And in the instantiation within the function implementation, replace <T, X> with <Ts...> to "expand" the parameter pack.
The result then looks like this:
template <template<class...> class TemplatePrototype,
class ... Ts>
void doSomething()
{
TemplatePrototype<Ts...> aTemplateTs;
aTemplateTs.doSomethingElse();
}
Live demo
Given a template like
template<int dim> class Point { ... };
this template can be instantiated explicitly like
template class Point<0>;
template class Point<1>;
template class Point<2>;
template class Point<3>;
instead of instantiating every template individually like above, I would like to instantiate them recursively with one call like
template class RecursiveInstantiate<Point, 3>;
where RecursiveInstantiate<T, i> would instantiate T<i>, T<i-1>, ..., T<0>. Is it somehow possible to create such a class RecursiveInstantiate? If it is not possible, do you know a way to do it with the preprocessor?
In fact I am interested in generalizing this for classes with multiple template parameters likeNode<int i1,int i2,int i3> for all combination of i1,i2,i3 in {0,1,2,3}. But I hope to be able to work out this second part by myself.
Any advice, also an explanation why it is impossible what I want to achieve is appreciated.
Update: thank you for your comments so far. I see now more clearly where the problem really is. The line
template class Point<3>;
instantiates the template and exports its symbols to the object file. An instantiation of the form
template class RecursiveInstantiate<Point, 3>;
may instantiate the classes class Point<3>, class Point<2>, .... Apparently this only happens locally though. The templates are not exported to the object file. Maybe I will have to look for a solution using the preprocessor.
As I see now that I did not ask my question precisely enough in the beginning, I appreciate your answers and selected ones as correct.
Note: I am trying this on linux with g++/clang as compilers.
You could make a little Instantiator class:
template <unsigned int N> struct Instantiator
{
Point<N> p;
Instantiator<N-1> i;
};
template <> struct Instantiator<0>
{
Point<0> p;
};
Then simply add one explicit instantiation: template struct Instantiator<81>;
You can extend this idea lexicographically to any number of integral parameters.
As #Georg says, let's make it generic:
template <template <unsigned int> class T, unsigned int N> struct Instantiator
{
T<N> t;
Instantiator<T, N-1> i;
};
template <template <unsigned int> class T> struct Instantiator<T, 0>
{
T<0> t;
};
template struct Instantiator<Point, 82>;
You can do that like this:
template<int dim> struct Point {
static const int val = dim;
Point<dim - 1> p;
};
template<> struct Point<0> { ... };
That creates a template specialisation for the template parameter when it is 0 so the recursion stops there, and when you instantiate one like this:
Point<4>
It instantiates from Point<4> down to Point<0>. Then you can do
Point<4>::val
to access the value of that particular one.