Chicago C/C++ Users Group Message Board › Generic programming discussion

Generic programming discussion

Conrad W.
CWeisert
Chicago, IL
Post #: 21
I'm looking forward to next month's discussion of C++ templates. Do you think we'll have time to talk about both function templates and class templates?

Students are often perplexed by a minor problem with function templates, and I haven't come up with a satisfactory solution to give them. Consider this simple one from the STL:

template <class T>
inline const T& max ( const T& y, const T& y ) {return y < x? y: x;};

If x and y are of different types, even comparable ones, a call will be ambiguous. Someone usually suggests generalizing the function like this:

template <class T1, class T2>
inline T1 max ( const T1& y, const T2& y ) {return y < x? y: x;};

Although it will work for more cases than the original, it may fail because we had to choose one of the types for the return value, which may not fit. Some student usually suggests specifying a convention in which the argument with the larger range should always be coded on the left, but that seems awfully contrived. One can think of a language extension that would solve this problem, and perhaps one of them is under consideration now, but that doesn't help today's programmer.

Any recommendations either on the code itself or on what to advise students?
Nevin ".
nliber
Libertyville, IL
Post #: 5
There are many, many issues with min and max. Here are some references:

Andrei Alexandrescu:
http://www.ddj.com/cp...­

Dr. Alexandrescu talks about using a type trait to figure out what to return.

Alex Stepanov:
http://www.stlport.or...­
http://www.stepanovpa...­
http://www.stepanovpa...­

Dr. Stepanov talks about stability; i.e.,

return x < y ? y : x

can be different from

return y < x ? x : y

for arbitrary types (and that he got max wrong in the STL, from the stability point of view).

I don't think even a language extension can solve it. In general, there may not be a "larger range" ordering between any two arbitrary types.

I want to point out that there is a big difference between the one type and two type cases above; namely, the former returns by const reference (you might also want to add a non-const version) while the latter returns by value.

Of course, I can just punt the return type problem up to the caller:

template<typename T1, typename T2>
boost::variant<T1&, T2&>
max(T1& t1, T2& t2)
{ if (t2 < t1) return t1; return t2; }

template<typename T1, typename T2>
boost::variant<T1 const&, T2 const&>
max(T1 const& t1, T2 const& t2)
{ if (t2 < t1) return t1; return t2; }

but I'm sure that isn't really a satisfactory answer for anybody.
Conrad W.
CWeisert
Chicago, IL
Post #: 23
C++ insiders, not to mention Java gurus, strongly discourage, even condemn, using preprocessor macros to generate generic functions. Yet I believe that
#define MAX(x,y) ((x) > (y) ? x : y)
works fine for all cases while the template function may either fail to instantiate at compile time or yield the wrong answer at run time.
Nevin ".
nliber
Libertyville, IL
Post #: 6
Please read the Dr. Alexandrescu article I referenced previously, where he goes into a lot of detail comparing the macro solution with other possible solutions, and he points a few situations where the macro implementation does the wrong thing.

One is the general problem that macro semantics are not the same as function semantics. In this case, one of the arguments is always evaluated twice. The caller has to know he is calling a macro, not a function, and avoid passing in parameters that may have side effects.

Another is that slicing of an object can occur. Read the article for more details.

Now, you can say that the macro solution is the best compromise, but to say that the macro implementation works correctly in all cases is just plain wrong.

Also, you didn't comment on stability (as Dr. Stepanov brought up in his articles). Do you believe it isn't important?
Conrad W.
CWeisert
Chicago, IL
Post #: 24
Sorry. What I meant by "all cases" was just for all legitimate combinations of parameter types. (more later)
Conrad W.
CWeisert
Chicago, IL
Post #: 25
I hadn't intended to start such a spirited debate with my simple example. Here are two final (perhaps) comments:

First, I'd be delighted to read professor Stepanov's material, and may do so eventually, but it's not helpful to send me a link to several hundred pages of material with a general suggestion that I should read it.

Second, I interpret Dr. Andeandrecu's analysis as generally supportive of my original point. With the consensus opinion that it's generally poor practice to generate side effects from function parameters, the macro version is more generally applicable than the STL version. A reasonable programmer is far more likely to want to code
. . . max(x, y+1) . . .
than
. . . max(x,++y)
Finally, if we follow the common convention for macro names, the call would be
. . . MAX(a,b)
which would remind the programmer that side effects might fail.
Powered by mvnForum

Sign up

Meetup members, Log in

By clicking "Sign up" or "Sign up using Facebook", you confirm that you accept our Terms of Service & Privacy Policy