Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2004-02-20 16:03:57


Brian McNamara <lorgon_at_[hidden]> writes:

> On Fri, Feb 20, 2004 at 12:25:49PM -0500, David Abrahams wrote:
>> Brian McNamara <lorgon_at_[hidden]> writes:
>> > On Thu, Feb 19, 2004 at 11:35:13PM -0500, David Abrahams wrote:
>> >> Brian McNamara <lorgon_at_[hidden]> writes:
>> >> > (Despite the fact that no one wants to hear it, I would feel remiss if I
>> >> > didn't play Chicken Little and say "Fool's gold! Qualified calls and
>> >> > template specialization are the one true path to such customization!
>> >>
>> >> You'd be wrong. It'd be nice if it were true, but qualified calls
>> >> are subject to order dependencies, among other problems.
>> >
>> > I'm not clear about this.
>> >
>> > // lib.hpp
>> > namespace lib {
>> > template <class T> void f(T);
>> > template <class T> void g(T x) { lib::f(x); }
>> > }
>> >
>> > // user.hpp
>> > #include "lib.hpp"
>> > namespace user {
>> > struct MyClass {};
>> > }
>> > namespace lib {
>> > template <> void f( user::MyClass ) { /* print "foo" */ }
>> Not an overload.
>
> Yes, I know. Chicken Little says
>
> Qualified calls and _template_specialization_ are the one true path
> to such customization! [emphasis added]

But he's wrong. As I've been trying to say, qualified calls in a
function template are bound at the point of definition, so if a better
overload comes later it isn't considered. That's why you should use
parens.

>> > }
>> >
>> > // user.cpp
>> > #include "user.hpp"
>> > int main() {
>> > user::MyClass m;
>> > lib::g(m);
>> > }
>> >
>> > Would that not print "foo"? What is the order dependency?
>>
>> That's a specialization. Actually, there'd still be an order
>> dependency if g wasn't a function template, but that's beside the
>> point.
>
> I'm not sure what your second sentence there is trying to tell me; can
> you give a short example?

Simple: specializations that follow the point of instantiation aren't
considered. This program exits with an error:

  template <class T>
  int f(T) { return 1; }

  int main() { return ::f(0); }

  template <> int f(int) { return 0; }

> (If g isn't a function template, what would
> it be?)

A regular function.

>> > (I don't think I have access to a compiler that supposedly does
>> > this right, or else I'd try it myself.) What are the other
>> > problems? (I know one: function templates can't be "partially"
>> > specialized, which means you sometimes need to use a class
>> > helper, ugh.)
>>
>> specialization interacts badly with overloading too:
>>
>> template <class T> int f(T);
>> template <> int f(int*);
>> template <class T> void f(T*);
>>
>> int x = 0;
>> int y = f(&x); // error; can't convert void to int.
>
> Indeed; recall that part of Chicken Little's thesis is
>
> All designs based on overloading or ADL will end in tears!

There's no ADL here.

> the relevant part here being "Overloading bad!" (in the context of
> library/user customization designs).

I understand this purist's POV, but then, "Specialization Bad", too,
for similar but even worse reasons:

  template <class T>
  struct fu
  {
      int bar();
  };

  template <>
  struct fu<int>
  {
      typedef whiskey bar;
  };

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk