$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: George A. Heintzelman (georgeh_at_[hidden])
Date: 2002-10-29 10:25:04
I went back and did a little more homework and found a few things out 
which I think may have some implications for how we ought to organize 
boost namespaces. My conclusion is that we probably ought to move boost 
classes which are intended to be derived from by the user into 
sub-namespaces which are brought into boost proper with using 
declarations. This will inhibit Koenig lookup on the whole of boost for 
user classes derived from these classes.
More detail on my thinking follows:
> From: "George A. Heintzelman" <georgeh_at_[hidden]>
> > namespace MyNS {
> >   class Iterator: public boost::bidirectional_iterator_helper<...> {
> >   };
> >
> > // I need some utility functions on the iterators:
> >   int type(Iterator it);
> > };
> >
> > int main() {
> >    Iterator it;
> >    type(it);
> > }
> > `template<class T> class boost::type' is not a function, conflict with
> `int MyNS::type(MyNS::Iterator)' in call to `type'
> > Is there anything I (or boost) can do?<
> 
> Yes, you can rename type() to something less collision prone. Functions that
> are intended to be used via argument dependent lookup must have distinctive
> names. "iterator_type" would be better, but probably not enough; use
> something more descriptive.
I don't like this answer. I understood that the idea of Koenig lookup 
was to allow me to use those kinds of short names without having to say 
myprefix_shortname(iterator) every time. In my case in particular, I am 
replacing pointers with a new iterator type where we had functions 
type(Record *) now getting replaced by type(Iterator), and type() isn't 
the only name involved (I'd have to rename all the others for 
consistency), so it's not a feasible solution for me.
So I went back to the standard and noticed that arg-dependent lookup 
does *not* follow unnamed namespaces or using declarations in order to 
look things up. So as a bit of a hack I tried changing boost/type.hpp 
as so:
namespace boost {
  // Just a simple "type envelope". Useful in various contexts, mostly 
to work
  // around some MSVC deficiencies.
  namespace type_detail {
    template <class T>
    struct type {};
  }
  using namespace type_detail;
}
This doesn't cause anything in boost not to find boost::type when it 
needs it (as far as I can tell, anyway), but it does inhibit Koenig 
lookup from conflicting on it.
I didn't use the unnamed namespace, because that would lead to 
different instantiations of boost::type in different translation units, 
something I thought people might not want; however it also allowed my 
code to compile. I didn't use boost::detail, because that would bring 
in all the other names in boost::detail. Using 'using 
type_detail::type;' also didn't work with g++ 3.2, though it worked 
with Intel's compiler v7 beta. I'm not sure which one is right, though 
I suspect Intel is (I'll be submitting a bug report to the gcc people 
if I convince myself of that).
However, I didn't like the idea of having to dig through boost to 
figure out which names ought to be protected from Koenig lookup. 
Instead, we ought to prevent Koenig lookup from searching boost for the 
user classes derived from boost classes, but we may want other 
interfaces specific to those classes. For that, another option which 
seems to be feasible would be to put class templates which are intended 
to be derived from (such as bidirectional_iterator_helper) in their own 
sub-namespaces, which are then brought back into boost visibility with 
using declarations. In a test, for example, this seems to work, where 
it fails without the foo::sub namespace:
namespace foo {
  namespace sub {
    template <class T> 
    class bar {
    };
  }
  using namespace sub;
  
  class base {
    int b;
  };
}
namespace baz {
  struct X: public foo::base {
    int x;
  };
  void bar(X x);
}
int main() {
  baz::X myx;
  bar(myx);
}
Am I way off base? I think this is something that boost could do to 
make interfaces based around argument-dependent lookup more feasible.
George Heintzelman
georgeh_at_[hidden]