Home

Template Specialization in C++

|
Updated:  
2016-03-26 08:29:41
|
From The Book:  
C++ Essentials For Dummies
Explore Book
Buy On Amazon

Some templates don’t go together quite as easily as you might expect because they express a concept that doesn’t translate the same way for every data type. For example, when you use stringify to turn a data type into its string representation, the technique differs based on data type. For example, when you want to use stringify on an int, you might use the following template:

#include <iostream>
#include <sstream>
using namespace std;
template<typename T> inline string stringify(const T& input)
{
    ostringstream output;
    output << input;
    return output.str();
}
int main()
{
    // This call works as expected.
    cout << stringify<int>(42) << endl;
    // This call truncates.
    cout << stringify<double>(45.6789012345) << endl;
    return 0;
}

The stringify() function accepts any data type and simply uses an ostringstream to convert input to a string. This approach works fine for the first call in main(), which is an int. However, when the code uses it for a double, the result is truncated as shown here:

42
45.6789

You can fix this problem by adding special handling for a double. Here is the modified form of the example (as shown in StringifyDouble) that accommodates a double.

#include <iostream>
#include <sstream>
#include <iomanip>
#include <limits>
using namespace std;
template<typename T> inline string stringify(const T& input)
{
    ostringstream output;
    output << input;
    return output.str();
}
template <> inline string stringify<double> (const double& input)
{
    ostringstream output;
    const int sigdigits = numeric_limits<double>::digits10;
    output << setprecision(sigdigits) << input;
    return output.str();
}
int main()
{
    cout << stringify<int>(42) << endl;
    cout << stringify<double>(45.6789012345) << endl;
    return 0;
}

When you run this example, you see the expected result because the double form of the template uses setprecision to modify the ostringstream value. As a result, you see the following output:

42
45.6789012345

As things sit with C++ today, you must create a special template for each data type that requires it. Theoretically, if C++ ever gets a typeof() function, you could detect the data type and add a switch to perform specialized processing within a single template.

The typeid() function could work as a substitute for typeof(), but it’s vendor-specific and not implemented in every version of C++. If you choose to use the typeid() function, make sure you know which compiler your organization will use to compile the application code.

You may have also noticed the inline keyword used for the template in this example. The inline keyword tells the compiler to place the code created by the template in line with the code in which it appears, rather than out of line as a separate function call. In some cases, such as this stringify() function, the result is code that executes faster.

The compiler is under no obligation to comply with the inline keyword. In addition, you want template code placed out of line when it must perform some level of instantiation or it doesn’t represent critical path code that the application can call often.

About This Article

This article is from the book: 

About the book author:

John Paul Mueller is a freelance author and technical editor. He has writing in his blood, having produced 100 books and more than 600 articles to date. The topics range from networking to home security and from database management to heads-down programming. John has provided technical services to both Data Based Advisor and Coast Compute magazines.

Jeff Cogswell has been an application developer and trainer for 18 years, working with clients from startups to Fortune 500 companies. He has developed courses on C++ and other technologies.