Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-06-27 09:59:29


On Wednesday 27 June 2001 06:54, you wrote:
> Doug,
>
> I've putting together some test cases for the new macros that function
> added to config.hpp: and I'm struggling to understand
> BOOST_NO_DEPENDENT_BASE_LOOKUP.
>
> First off, this is defined for Borland compilers, but all the function
> tests compile OK with bc 5.51: am I missing something here?

It's essentially for optimization. For instance, the following code:
function<int, int> f;
f = negate<int>(); // #1

At #1, Borland will choose to construct a function<int, int> object from the
negate<int> object, then call f's copy assignment operator. This results in
two allocations of "negate<int>" objects and one deallocation, so it is
inefficient. At the time, I had though this was a name lookup problem (it
wasn't finding the templated operator= from the base class), so I added the
macro, which "fixed" the call. Now it didn't create the temporary (that's
good).

Well, I was wrong and Borland was right. The best overload candidate is
indeed to use f's copy assignment operator after creating a temporary
function<int, int> object. This was very surprising to me, so I'll explain
further.

You might be sorry you asked :)

Consider this little tidbit of overload resolution:

struct Foo {
  template<typename T> Foo& operator=(const T&);
};

struct Bar : public Foo {
  template<typename T> Bar(T);
  Bar& operator=(const Bar& other);
};

Bar b;
b = 5;

So what happens at b=5? Clearly the candidates are either:
1) a call to Foo::operator=(T). This requires:
        a) b is converted to type Foo& (Rank: Conversion, 13.3.3.1.1 table 9)
        b) 5 is copy-initialized. Since the types are equal except for cv-quals, it
binds directly (8.5.3p5) and is therefore considered the identity conversion
(Rank: Exact Match, 13.3.3.1.4p1)

2) a call to Bar::operator=(const Bar&)
        a) no conversions required, Rank: Exact Match
        b) other is copy-initialized. Since int can be implicitly converted to Bar
and then to const Bar&, the reference binds directly. Rank: Exact Match (!)

So #2 is better than #1.

What's the resolution? BOOST_NO_DEPENDENT_BASE_LOOKUP is the wrong name for
the macro for sure - it isn't a compiler deficiency at all. Most likely the
macro should be removed and I'll work on a way to deal with the copy
efficiency problems.

> Secondly, you do realise that members of template base classes are not
> visible to derived classes anyway - you have to use either:
>
> base_type::member_name
>
> (which breaks VC6), or use:
>
> this->member_name
>
> which seems to work everywhere.
>
> If I've misunderstood the intent of this macro (quite likely!), apologies.
>
>
> - John Maddock
> http://ourworld.compuserve.com/homepages/john_maddock/

        Doug


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