----- Original Message ----- From: "Douglas Gregor" <[EMAIL PROTECTED]>
> On Tuesday 19 November 2002 04:44 pm, Paul Mensonides wrote: > > Clever type traits are one thing, but they are a side-effect of the > > solution to a more general problem. Specifically, one template function > > declaration can permanently break an overload set--even if it is not > > selected. The solution to this is obvious, if type deduction yields > > nonsense, it should fail. It just so happens that we could exploit that > > solution in significant ways with traits and expression validity checking. > > I don't think it's quite so clear-cut, because we have to define what you mean > by "nonsense", and I'm not sure you'll find agreement. The committee chose > one view of nonsense: trying to form any type that isn't a C++ type (e.g., > typename int::foo) is nonsense, so deduction fails. This isn't what that section means however. It is only a list a few cases of "trying to form any type that isn't a C++ type." > But we're talking about a > whole new dimension of nonsense, where we want it to say "anything that can't > compile is nonsense". More or less, yes. Anything that is not semantically valid causes type deduction failure. > I have to wonder if this makes the problem you > cite---that one function template declaration can permanently break an > overload set---even worse. We're not talking about one brilliantly-written > function template declaration, we're talking about one that is poorly written > because it is too general. It's an error that should be corrected, but the > user won't ever actually see this error because the function template will > never make it into the overload set. I'm talking about the strict interpretation of the standard (14.8.3)--not what current compilers do. Type deduction happens *before* overload resolution--i.e. in the process or building a candidate set. The template function just has to be visible. So, in order for the function to "never make it into the overload set," it has to fail type deduction (i.e. not pass and _not_ error). template<unsigned> class x { }; template<class> class y { }; template<class T> void f( x<sizeof(T)>* ); template<class T> void f( y<T>* x, y<T>* y ); f<void>(0, 0) // error struct z { }; template<class T> void g( T z::*, int ); template<class T> void g( int ... ); g<int&>(0, 0) // error > Also note that this change is a huge problem for backward compatibility. That > badly broken function template from above is silently useless on C++0x, but > step back to C++98/C++02 and its going to fail. This isn't a case of a "badly broken function template," nor is a case of it being "silently useless." It can be a perfectly worthwhile function template. All that has to happen is its declaration cannot be instantiated with a certain template arguments, where doing so does not match one of the listed criteria for type deduction failure in 14.8.2. Remember, this happens *before* overload resolution, so it happens with every function template that is in scope every time a call is made to a function with that name. A given template function can *not* be selected in only two ways--1) it fails type deduction which causes it to be invisible to overload resolution, or 2) it passes type deduction but is not selected by regular overload resolution. As far as compatibility goes, this is a non-issue. What once was an error would now be allowed (0x). That is not the same thing as something that *was* allowed and later was an error. This change would do several things, 1) cleanup that section of the standard, 2) unify the rules with declaration instantiation ala member functions, 3) give us a huge set of tools to work with for generic programming, and 4) close a potentially serious hole in the C++ overload mechanism. What this change *wouldn't* do is alter the results on overload resolution in any way, nor would it allow more functions into the candidate set. The *only* change would be that functions would be removed automatically if declaration instantiation makes no sense. This is just professional-quality design here, folks. As it is now, it is only half-designed. Furthermore, defining "nonsense" in the context which I use it is not difficult. If type deduction yields a function declaration that would be invalid if directly used in the source, then type deduction fails. Obviously, it can be worded better than that, but you get the idea. > > *why* something is invalid in the general sense. Also, the "sizeof" trick > > is open-ended. Any possible future language primitives will only give us a > > few of the things we need, and we'll still have to do the rest anyway. > > > > Paul Mensonides > > ... but don't forget that once we get more language primitives, that will > enable new tricks as well. Yes. My point is that whatever gets added to 0x is not going to solve all of our needs. We should never throw away worthwhile tools--even if some of them make us bend over backward to accomplish something (i.e. the sizeof hack). Paul Mensonides _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost