Previous section   Next section

Imperfect C++ Practical Solutions for Real-Life Programming
By Matthew Wilson
Table of Contents
Chapter 23.  Template Constructors


23.1. Hidden Costs

Let's look at another class, String:



class String


{


public:


  typedef std::string const  &value_type;


public:


  explicit String(std::string const &value);


  explicit String(char const *value);


public:


  std::string const &GetValue() const;


  . . .



We can use this as we did Double, with the current definition of Wrapper:



typedef Wrapper<String>  String_t;





std::string       ss("A std::string instance");


String_t          s1("A c-style string"); // Ok


String_t          s2(ss);                 // Ok, but . . .



Both the constructors compile, and the code works as expected, but there is a hidden gotcha. The construction of s2 results in the creation of two copies of the string ss, where we only expect and want one. The extra copy is created because compilers instantiate a template based on the types of the arguments expressed to it, without any consideration as to how they might be used within it. Thus, the construction of s2 is actually done by a constructor equivalent to the following:



Wrapper<String>::Wrapper(String s)


  : m_value(s)


{}



Imperfection: The C++ template mechanism instantiates a template based on the arguments to it, and takes no account of how, or in what form, those arguments are subsequently used within the templates. This can lead to the generation of inefficient and/or erroneous code since temporary instances of class type may be created during the forwarding of arguments through the template.



      Previous section   Next section