Addendum to "Tiny Template Tidbit"

Addendum to "Tiny Template Tidbit"

By Oliver Schoenborn

Overload, 11(54):, April 2003


I would like to add a few comments to the Overload 47 article that I wrote, entitled "Tiny Template Tidbit". They don't change conclusions of the article but may prevent some confusion.

First, as kindly pointed out to me by Alan Griffiths and Chris Main, I misuse the term "partial specialization".

On page 16, 2nd column, I say "what we need is a template overload for pointers". No problem so far. I then explain briefly that it is somewhat like partial specialization available for classes but not the same. Unfortunately, the code examples contain C++ comments that describe some syntax as "partial specialization" applied to functions (not supported in C++). They should instead read "overload for ...". I must have had a few beers too many that day.

Secondly, a minor mistake in the formatting of the two lines "Advantages:" and "Disadvantages:". The typeface makes it look like there are three paragraphs of advantages and almost two pages of disadvantages! The disadvantages use up only three paragraphs as well.

Finally, an interesting mistake was pointed out to me by Chris Main. It appears that a bug in the SGI MipsPro C++ compiler allows the compiler to pick the intended getCoord() function template even though, according to the Standard, it should not be able to. This is worth expanding upon. Let me recall the summary here:

I showed how a processor (object or function) that uses data from a set of objects of a certain type can be generalized with a very small number of lines of code, using templates and specializations, such that the processor doesn't need to be changed when the data structure changes. More specifically, your processor object or function is able to extract the needed data from the container elements, regardless of whether the container element type

  1. Is the data, or is a pointer to the data (as opposed to containing it)

  2. Is an object or a pointer to an object, containing the data

  3. Makes data available as attribute OR method (which we don't address in this addendum)

Finally, the compiler does this for you automatically, without requiring your intervention.

Two of the functions and templates used were:

/// General function template
template <class P> inline
const Coord& getCoord(const P& p) {
  return p.coords;
}

/// Overload for pointers to things
template <class P>
const Coord& getCoord(const P* p) {
  return p->coords;
}

where P is one of the six types of data described in 1-3 above. As Chris pointed out to me, given the code fragment

Struct Point {Coord coord;};
Point coord;
getCoord(&coord);

the compiler has two choices for getCoord() :

  1. getCoord<Point*>(const Point*&)

  2. getCoord<Point>(const Point*)

Which one will the compiler choose? The one we want (#2) or #1? With SGI's mipspro compiler, it chooses #2. With gcc 2.95, it chooses #1. I thought it was a bug with gcc but Chris gives good evidence that it is the other way around: overload resolution states that the compiler must choose the most "specific" template, which is #1, since the parameter is a pointer to the type rather than just the type.

This could seem like a major problem for the techniques discussed in that article but really it isn't because the concepts used were sound, it's just the technique used to implement them that got side-tracked onto a wrong path. The fundamental problem is how to tell the compiler to deal with two separate cases of data, one a type, the other a pointer to a type (a "pointer type"). This is easy with partial specialization of a class that does nothing for types, and does a dereference for a pointer type:

template <typename P>
struct Obj {
  static const P& getObj(const P& p) {
    return p;
  }
};
// partial specialization for pointer
// types
template <typename P>
struct Obj<P*> {
  static const P& getObj(const P* p) {
    return *p;
  }
};

They replace two of the four getCoord() overloads mentioned in the article, namely the ones with pointer types as parameter, and are used by calling

getCoord( Obj<T>::getObj(p) )

instead of

getCoord(p)

In any case, I hope you found the article interesting and maybe even useful. Thanks to Alan and Chris for sending feedback. As usual, I find that writing articles is fun and challenging, but I inevitably seem to learn a lot more than I could have expected from the feedback of readers. I encourage you to give it a try, write an article for Overload!

References

[Stroustrup] Bjarne Stroustrup, C++ Programming Language , 3rd ed.

[Alexandrescu] Andrei Alexandrescu, Modern C++ Design

[Schoenborn] Oliver Schoenborn, "Tiny Template Tidbit," Overload 47






Your Privacy

By clicking "Accept Non-Essential Cookies" you agree ACCU can store non-essential cookies on your device and disclose information in accordance with our Privacy Policy and Cookie Policy.

Current Setting: Non-Essential Cookies REJECTED


By clicking "Include Third Party Content" you agree ACCU can forward your IP address to third-party sites (such as YouTube) to enhance the information presented on this site, and that third-party sites may store cookies on your device.

Current Setting: Third Party Content EXCLUDED



Settings can be changed at any time from the Cookie Policy page.