Online Book Reader

Home Category

Professional C__ - Marc Gregoire [362]

By Root 1244 0
either an instance of true_type or false_type. The process() function template accepts a single argument and will call the process_helper() function with the second parameter defined as follows:

typename is_integral::type()

This uses is_integral to see if T is an integral type. Calling ::type will return the resulting integral_constant, which can be a true_type or a false_type. The process_helper() function needs an instance of true_type or false_type as second parameter, so that is the reason for the two empty brackets behind ::type. Note that the two overloaded process_helper() functions use nameless parameters of type true_type or false_type. They are nameless because they don’t use those parameters inside their function body. If you don’t like this syntax, you might as well write the following:

void process_helper(const T& t, true_type tt)

However, because tt will not be used in the body of the function, this will most likely trigger a warning from your compiler saying that tt is unused.

Using Type Relations

There are three type relations available: is_same, is_base_of and is_convertible. They all work similarly. This section gives an example of how to use is_same.

The following example defines a same_helper() function template. It accepts two constant references and one Boolean value. The function prints the two values followed by a specific string depending on the value of the Boolean parameter. The same() function template uses the is_same type traits feature to figure out whether the two given arguments are of the same type or not and then calls the same_helper() function. It uses ::value because the same_helper() function requires a Boolean value true or false. Using the same() function template is very easy as is shown in the main() function:

template

void same_helper(const T1& t1, const T2& t2, bool b)

{

cout << "'" << t1 << "' and '" << t2 << "' are ";

cout << (b ? "the same types." : "different types.") << endl;

}

template

void same(const T1& t1, const T2& t2)

{

same_helper(t1, t2, is_same::value);

}

int main()

{

same(1, 32);

same(1, 3.01);

same(3.01, string("Test"));

}

Code snippet from TypeTraits\is_same.cpp

The output should be as follows:

'1' and '32' are the same types.

'1' and '3.01' are different types

'3.01' and 'Test' are different types

Using enable_if

First, a little warning before continuing with enable_if. Using enable_if requires knowledge of a feature called Substitution Failure Is Not An Error (SFINAE), a complicated and obscure feature of C++. This section explains the basics of SFINAE with an example.

The previous example with the same() and same_helper() function templates can be rewritten into one overloaded check_type() function template by using the enable_if type traits transformation as follows:

template

void check_type(const T1& t1, const T2& t2,

typename enable_if::value>::type* p = nullptr)

{

cout << "'" << t1 << "' and '" << t2 << "' ";

cout << "are the same types." << endl;

}

template

void check_type(const T1& t1, const T2& t2,

typename enable_if::value>::type* p = nullptr)

{

cout << "'" << t1 << "' and '" << t2 << "' ";

cout << "are different types." << endl;

}

int main()

{

check_type(1, 32);

check_type(1, 3.01);

check_type(3.01, string("Test"));

}

Code snippet from TypeTraits\enable_if.cpp

The output will be:

'1' and '32' are the same types.

'1' and '3.01' are different types.

'3.01' and 'Test' are different types.

This example defines one function called check_type(), which is overloaded on its third parameter. The third parameter for the first overload looks as follows:

typename enable_if::value>::type* p = nullptr

It first uses is_same to check whether the two types are the same or not and gets the value of that result with ::value. This value is given to enable_if, and ::type is used to get the resulting type. When the argument to enable_if is true,

Return Main Page Previous Page Next Page

®Online Book Reader