![]() | |
![]() ![]() |
![]() | Imperfect C++ Practical Solutions for Real-Life Programming By Matthew Wilson |
Table of Contents | |
Chapter 23. Template Constructors |
23.2. Dangling ReferencesTo accommodate the Double and String classes, we can change the nondefault constructor of Wrapper to take T const&, rather than just T. This enables the string instance to be passed through the template to the underlying type without the unnecessary copy, and it passes the double by const-reference rather than by value. If anything, this is possibly more efficient in theory, since the double is probably 64 or 80 bits, and the reference is 32 or 64 bits; in practice it will probably make no difference since compilers will be able to optimize the outer call to the inner initialization without any trouble. template <typename T> class Wrapper : public T { . . . template <typename T1> explicit Wrapper(T1 const &t1) : base_class_type(t1) {} . . . Naturally, you'll be wondering now about what happens when we need to pass through a non-const reference, as required by the constructor for our next class, StringModifier (Listing 23.3). Listing 23.3.
class StringModifier
{
public:
typedef std::string const Value_type;
public:
explicit StringModifier(std::string &value)
: m_value(value)
{}
public:
std::string const &GetValue() const;
void SetValue(std::string const &value);
private:
std::string &m_value;
};
For the current definition of the Wrapper, the answer is that it won't work.
typedef Wrapper<StringModifier> StringModifier_t;
std::string ss("A std::string instance");
StringModifier_t s1(ss); // Error!
What's worse is that many compilers will actually compile this,[2] without warning, with the first version of the Wrapper, This leaves s1 holding onto a non-const reference to a temporary that, once the constructor returns, no longer exists! Buenas noches, Señor Core-Dump!
|
![]() | |
![]() ![]() |