Non-type template arguments

The usual method to employ templates is to supply a type to its parameters. Most C++ beginners at some point have used container, and supplied the value type of the container (and possibly more types for the other parameters such as an allocator type, which are in fact template template arguments).

Less common (in my experience) are nontype template arguments. A simple definition would look like this:

template <typename T, T nontypeParam>
class A
{
...
};

A<int,10> a;

There is also the option of specifying the type directly in the definition:

template <int i>
class Factorial 
{
   enum { value = i*Factorial<i-1>::value };
};

template<>
class Factorial<0>
{
   enum { value = 1; }
}

Factorial<10>::value;

In the example code above we’re using Template MetaProgramming (TMP). All of the calculation in TMP are done during template instantiation at compile time. Meaning a tradoff of a longer compilation, for a faster runtime.

Generally, the rules for non-type arguments are that the values must be known by the compiler or linker when building.

There are a few limitations (see this section for the allowed non types [temp.param / 14.1.4]). The most notable has to do with string literals. The reason for the complication with literals is because identical literals can be stored at different memory locations. The solution is to create a variable to hold the char string with external storage:

extern const  char  lostInSpaceRobot[] = "Robot";

An interesting use case is to access some kind of setting through an interface:

template <const char * nameStr>
class UserPhrase
{
public: 
	static string Phrase() 
	{
		static bool firstTime = true;
		static string myPhrase; 

		if (!firstTime)
		{
			return myPhrase;
		}
		else 
		{
			// Can be set from a lookup table etc. 
			myPhrase = "Danger Will Robinson!";
			firstTime = false;
		}

		return myPhrase;
	}
};

extern const  char  lostInSpaceRobot[] = "Robot";

int main()
{
	string myCatchPhrase = UserPhrase<lostInSpaceRobot>::Phrase();

	cout << lostInSpaceRobot << "'s catch phrase is: " << myCatchPhrase << endl;

From then on any requests at runtime for the same type UserPhrase already has had the value set. As I hinted at this can be quite useful when the data requested could be obtained from multiple sources, as it will provide a simple interface.

Leave a Reply

Your email address will not be published. Required fields are marked *