Online Book Reader

Home Category

Professional C__ - Marc Gregoire [360]

By Root 1127 0
template altogether by defining a function template that will deduce the type automatically:

template

void loopFunc(FuncType f)

{

Loop::Do(f);

}

int main()

{

loopFunc<2>(bind(DoWork2, "TestStr", placeholders::_1));

}

Code snippet from LoopUnrolling\LoopUnrolling.cpp

The output will be the same as before. As you can see in the main() function, you don’t need to specify the type of the DoWork2() function anymore. The loopFunc() function template will automatically deduce this type and use it to instantiate the Loop template.

Printing Tuples

This example will use template metaprogramming to print the individual elements of a C++11 std::tuple. Tuples are explained in Chapter 16. They allow you to store any number of values, each with its own specific type. A tuple has a fixed size and fixed value types, determined at compile time. However, tuples don’t have any built-in mechanism to iterate over their elements. The following example shows how you could use template metaprogramming to iterate over the elements of a tuple at compile time:

template

class tuple_print

{

public:

tuple_print(TupleType t) {

tuple_print tp(t);

cout << get(t) << endl;

}

};

template

class tuple_print<0, TupleType>

{

public:

tuple_print(TupleType t) {}

};

int main()

{

typedef tuple MyTuple;

MyTuple t1(16, "Test", true);

tuple_print::value, MyTuple> tp(t1);

}

Code snippet from PrintTuple\PrintTuple.cpp

Like it is often the case with template metaprogramming, this example is again using template recursion. There is a tuple_print template class that accepts a size integer and the type of the tuple. It then recursively instantiates itself in the constructor and decrements the size on every call. A partial specialization of the tuple_print class for a zero sized tuple stops the recursion. The main() function shows how this tuple_print template class could be used.

If you look at the main() function, you can see that the line to use the tuple_print template looks a bit complicated because it requires the size of the tuple and the exact type of the tuple as template arguments. This can be simplified a lot by introducing a template helper function that will automatically deduce the template parameters. The simplified implementation is as follows:

template

class tuple_print_helper

{

public:

tuple_print_helper(TupleType t) {

tuple_print_helper tp(t);

cout << get(t) << endl;

}

};

template

class tuple_print_helper<0, TupleType>

{

public:

tuple_print_helper(TupleType t) {}

};

template

void tuple_print(T t)

{

tuple_print_helper::value, T> tph(t);

}

int main()

{

auto t1 = make_tuple(167, "Testing", false, 2.3);

tuple_print(t1);

}

Code snippet from PrintTuple\PrintTupleSimplified.cpp

The first change made here is to rename the original tuple_print template class to tuple_print_helper. The code then implements a small function template called tuple_print(), which accepts the type of the tuple as a template argument and accepts the tuple itself as a function argument. The body of that function instantiates the tuple_print_helper template class. The main() function shows how to use this simplified version. Since you don’t need to know the exact type of the tuple yourself anymore, you can use the recommended make_tuple() together with the auto keyword to avoid having to write the tuple type yourself. The call to the tuple_print() function template is very simple:

tuple_print(t1);

You don’t need to specify the function template argument because the compiler can deduce this automatically from the supplied argument.

Type Traits

Type traits allow you to make decisions based on types at compile time. For example, you can write a template that requires a type that is derived from a certain type, or a type that is convertible to a certain type, or a type that is integral,

Return Main Page Previous Page Next Page

®Online Book Reader