Home

A Class Template With Multiple Parameters

 

Using Multiple Templates Types

When creating a template, you can specify more than one type. To do this, in the <> delimiters, after the first template type, enter a comma and declare an identifier that has a type and a name. Here is an example:

template <class TypeOfValue, __wchar_t c>
public ref class Description
{
public:
    Description();
    Description(TypeOfValue type) : Value(type)
    {
    }
    ~Description();
    void Show();
    String ^ Message;
    TypeOfValue Value;
};

In this case, the second type must be, and will be treated as, a constant. When creating the body of a method outside of the class, make sure you specify the second type. Also, in the operators that follow the name of the class, enter the name of the second type. Here is an example:

template <class TypeOfValue, __wchar_t c>
Description<TypeOfValue, c>::Description()
{
}

When implementing the method, use the second argument as you judge necessary. This should be easy because you know exactly its type. You can display its value or you can involve it in an operation of your choice. In the following example, the second type carries an indication of the message to be displayed. To identified that message, the value of the second argument is evaluated by a switch conditional statement:

template <class TypeOfValue, __wchar_t c>
void Description<TypeOfValue, c>::Show()
{
    switch(c)
    {
    case L'i':
    case L'I':
	Console::Write(L"Integer:   ");
	break;
    case L'c':
    case L'C':
	Console::Write(L"Character: ");
	break;
    case L'f':
    case L'F':
    case L'd':
    case L'D':
	Console::Write(L"Decimal:   ");
	break;
    }

    Console::WriteLine(L"{0}", Value);
}

When instantiating the class, you must specify the second type also. To do this, after the first type and its comma in the < and > operators, enter a constant value for the second type. Here are examples:

int main()
{
    // Call the function and pass it an integer value
    // Declare the variable on the stack heap
    Description<int, L'i'> iDscr;
    iDscr.Value = 246;
    iDscr.Message = L'i';
    iDscr.Show();

    // Call the function and pass it a character value
    // Declare the variable on the managed heap
    Description<__wchar_t, L'c'> ^ cDscr = gcnew Description<__wchar_t, L'c'>;
	
    cDscr->Value = 'G';
    cDscr->Message = L'c';
    cDscr->Show();

    // Call the function and pass it a double-precision value
    // Declare the variable on the managed heap
    Description<double, L'f'> ^ dDscr = 
		gcnew Description<double, L'f'>(355.65, L'f');
    dDscr->Message = L'f';
    dDscr->Show();

    return 0;
}

A Constant Template Parameter

Once again, remember that the second parameter is treated as a constant; therefore, it can be declared using the const keyword. Here is an example:

using namespace System;

template <class TypeOfValue, const __wchar_t c>
public ref class Description
{
public:
    Description();
    Description(TypeOfValue type, const __wchar_t msg)
		: Value(type), Message(msg)
    {
    }
    ~Description();
    void Show();
    __wchar_t Message;
    TypeOfValue Value;
};

template <class TypeOfValue, const __wchar_t c>
Description<TypeOfValue, c>::Description()
{
}

template <class TypeOfValue, const __wchar_t c>
Description<TypeOfValue, c>::~Description()
{
	Message = L'i';
}

template <class TypeOfValue, const __wchar_t c>
void Description<TypeOfValue, c>::Show()
{
	switch(c)
	{
	case L'i':
	case L'I':
		Console::Write(L"Integer:   ");
		break;
	case L'c':
	case L'C':
		Console::Write(L"Character: ");
		break;
	case L'f':
	case L'F':
	case L'd':
	case L'D':
		Console::Write(L"Decimal:   ");
		break;
	}

    Console::WriteLine(L"{0}", Value);
}

A Default Value for a Template Parameter

The second parameter of a class template can be assigned a default value. Based on the rules of a default value, this value would be used for the parameter if you don't supply a value for it. The default value can be assigned only in the declaration preceding the class creation. Here is an example:

using namespace System;

template <class TypeOfValue, const __wchar_t c = L'i'>
public ref class Description
{
public:
    Description();
    Description(TypeOfValue type, const __wchar_t msg)
		: Value(type), Message(msg)
    {
    }
    ~Description();
    void Show();
    __wchar_t Message;
    TypeOfValue Value;
};

template <class TypeOfValue, const __wchar_t c>
Description<TypeOfValue, c>::Description()
{
}

template <class TypeOfValue, const __wchar_t c>
Description<TypeOfValue, c>::~Description()
{
}

template <class TypeOfValue, const __wchar_t c>
void Description<TypeOfValue, c>::Show()
{
    switch(c)
    {
    case L'i':
    case L'I':
	Console::Write(L"Integer:   ");
	break;
    case L'c':
    case L'C':
	Console::Write(L"Character: ");
	break;
    case L'f':
    case L'F':
    case L'd':
    case L'D':
	Console::Write(L"Decimal:   ");
	break;
    }

    Console::WriteLine(L"{0}", Value);
}

When declaring a variable for the class, you can omit the second parameter if you want. In this case, the default value would be used. Here are two examples:

int main()
{
    // Call the function and pass it an integer value
    Description<int, L'i'> iDscr;
    iDscr.Value = 246;
    iDscr.Message = L'i';
    iDscr.Show();

    // Notice that the second argument is not specified
    // This means that the default value will be used
    Description<__wchar_t> ^ cDscr = gcnew Description<__wchar_t>;
	
    cDscr->Value = 'G';
    cDscr->Message = L'c';
    cDscr->Show();

    // Once again, notice that the second argument is not specified
    // The default value will be used for the parameter
    Description<double> ^ dDscr = gcnew Description<double>(355.65, L'f');
    dDscr->Message = L'f';
    dDscr->Show();

    return 0;
}

This would produce:

Integer:   246
Integer:   G
Integer:   355.65
Press any key to continue . . .

If you predict that the value of the first parameter can be assigned to the second one, you can use that first parameter's value and assign it to the second to be its default value.

A Class Template as a Template Parameter

When creating a class template, the first parameter can itself be a class template. To create such a class, inside the <> expression, include the type of declaration we have been using so far preceding a class creation. This expression itself becomes template parameter and can be used to precede the class keyword that is used to create a class template. Here is an example of such a class:

template <template <class SomeType> class ValueType>
public ref class Homework
{
};

Of course, a class must have been previously created so it can be used as a parameter. Here is an example:

template <class TypeOfValue>
public ref class Description
{
};

template <template <class SomeType> class ValueType>
public ref class Homework
{
};

Notice that both classes have nothing in common and they are not sharing any information.

 

Previous Copyright © 2006-2016, FunctionX, Inc. Next