![]() | |
![]() ![]() ![]() |
![]() | Imperfect C++ Practical Solutions for Real-Life Programming By Matthew Wilson |
Table of Contents | |
Chapter 23. Template Constructors |
23.3. Template Constructor SpecializationThat's okay, you say, because we have specialization. We can specialize the template for by-value, by-reference and by-const-reference. Unfortunately, that's not the case. The constructors are member templates and are, therefore, function templates. The language does not (yet[3]) support the specialization of function templates. What we might do, therefore, is to provide overloads for the constructor, as in:
Listing 23.4.template <typename T> class Wrapper : public T { . . . template <typename T1> explicit Wrapper(T1 t1) // by-val : base_class_type(t1) {} template <typename T1> explicit Wrapper(T1 &t1) // by-ref : base_class_type(t1) {} template <typename T1> explicit Wrapper(T1 const &t1) // by-const-ref : base_class_type(t1) {} . . . Unfortunately, we're so far away from civilization with this stuff that we're just about to sail off the edge of the C++ world. Combining the three examples so far—which test double, char const*, std::string const& and std::string&—we get the unpromising spectrum of behavior from a range of compilers shown in Table 23.1. When CodeWarrior and Comeau agree, I'm tempted to believe them even when they are at odds with GCC, Intel, and Visual C++ 7.1. But whether they're right or wrong is immaterial because we have some serious contradictions to deal with. This is a truly foul problem, and neither of the two answers to it are ideal.
Since all the compilers, or all the latest versions at least, support what we are trying to achieve in one form or another, one answer would be to use preprocessor discrimination in order to provide our bolt-ins and similar template classes with the appropriate constructors. The fly in this particular ointment is the combinatorial explosion. We have to support either two or three permutations for each argument. Since template constructors are used in types that, by definition, do not generally know of all the types to which they will be applied, we necessarily have to anticipate a large number of potential applications. In other words, we need to write these templates to provide template constructors up to a large number. In my own work I consider eight as a more than generous upper limit: a constructor with more than six parameters is getting pretty silly. Even restricting ourselves to only two parameter types for a template with eight constructors would still require 510 constructors, and this is without factoring in volatile and const volatile references! |
![]() | |
![]() ![]() ![]() |