A new writeup on Int-to-type idiom has been posted on More C++ Idioms wikibook. It is used to achieve static dispatching based on constant integral values. I'll finish the writeup of the idiom here with special attention to how int-to-type idiom can lead to infinite series of type instantiations and why. The idiomatic form of the Int-to-type idiom is given below.
template <int I>
struct Int2Type
{
enum { value = I };
typedef Int2Type<I> type;
typedef Int2Type<I+1> next;
};
The type typedef defined inside the template is the type itself. I.e, Int2Type<10>::type is same as Int2Type<10>. The next typedef gives the following type in order. However, compiler is not required to instantiate the next type unless and until two things happen: (1) an instance of the type is created or (2) an associated type is accessed at compile-time. For example, Int2Type<10> will be instantiated if one the following two things are written.
Int2Type<10> a; // a variable declaration.
typedef Int2Type<10>::type INT10; // accessing an associated type.
For kicks, lets see what happens if we add "::type" in the typedef of next.
template <int I>
struct Int2Type
{
enum { value = I };
typedef Int2Type<I> type;
typedef typename Int2Type<I+1>::type next; // Note change here.
};
int main (void)
{
Int2Type<10> i; // This instantiation will trigger an infinite chain.
}
For each instantiation of the Int2Type template, its "next" type is also instantiated because we are accessing the associated type defined inside the template. This leads to an infinite series of instantiations of the template with no end. Obviously, C++ compiler stops after predefined number of recursive instantiations with an error message. More formally, this problem is also known as infinite regress where the original problem reappears in the solution to the problem.
template <int I>
struct Int2Type
{
enum { value = I };
typedef Int2Type<I> type;
typedef Int2Type<I+1> next;
};
The type typedef defined inside the template is the type itself. I.e, Int2Type<10>::type is same as Int2Type<10>. The next typedef gives the following type in order. However, compiler is not required to instantiate the next type unless and until two things happen: (1) an instance of the type is created or (2) an associated type is accessed at compile-time. For example, Int2Type<10> will be instantiated if one the following two things are written.
Int2Type<10> a; // a variable declaration.
typedef Int2Type<10>::type INT10; // accessing an associated type.
For kicks, lets see what happens if we add "::type" in the typedef of next.
template <int I>
struct Int2Type
{
enum { value = I };
typedef Int2Type<I> type;
typedef typename Int2Type<I+1>::type next; // Note change here.
};
int main (void)
{
Int2Type<10> i; // This instantiation will trigger an infinite chain.
}
For each instantiation of the Int2Type template, its "next" type is also instantiated because we are accessing the associated type defined inside the template. This leads to an infinite series of instantiations of the template with no end. Obviously, C++ compiler stops after predefined number of recursive instantiations with an error message. More formally, this problem is also known as infinite regress where the original problem reappears in the solution to the problem.
Comments
An infinite series of instantiations of a class template is possible in general but unfortunately not with this one.
The fact that your compilers hit their limits before the condition was met is completely irrelevant: Given enough resources, this recursion will eventually always stop. This is not true for real infinite recursions.
template <typename T>
struct Type : Type< Type<T> > {};
it's really good :D
http://www.atlantisos.org/errormsg
That was me not going down a level and ending up with a template instantiated with 500 std::strings, which was instantiated from one with 499 std::strings etc... completely written out by the compiler.
you are more than welcome to have a look.