Topic: Question about ADL


Author: Derek.Long@cis.strath.ac.uk (Derek Long)
Date: Wed, 28 Apr 2004 15:57:23 +0000 (UTC)
Raw View
I have just been experimenting with g++ 3.4 and code that I thought was
compliant has raised compiler problems. Basically, if we have the
following code:

#include <iostream>

using std::cout;

template<typename T>
class A {
public:
 T f() {return T();};
};

template<typename T>
class B : public A<T> {
public:
 void g() {cout << f() << "\n";};
};

int main()
{
 B<int> b;
 b.g();
};


I would have expected the call to f() in g() to be OK. However, it isn't
for g++ 3.4:

checker.cc: In member function `void B<T>::g()':
checker.cc:14: error: there are no arguments to `f' that depend on a
template parameter, so a declaration of `f' must be available
checker.cc:14: error: (if you use `-fpermissive', G++ will accept your
code, but allowing the use of an undeclared name is deprecated)

Replacing f() with A<T>::f() will fix it. But is it a valid error, or is
  g++ 3.4 wrong?

Thanks for any insights anyone can offer on this.

Derek

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: AlbertoBarbati@libero.it (Alberto Barbati)
Date: Fri, 30 Apr 2004 03:15:13 +0000 (UTC)
Raw View
Derek Long wrote:
> I have just been experimenting with g++ 3.4 and code that I thought was
> compliant has raised compiler problems. Basically, if we have the
> following code:
 > <snip>

This has nothing to do with ADL which stands for "Argument Dependent
Lookup". All functions in your example take no argument, so ADL is never
involved. Maybe you are confusing ADL with the so called "two-phase name
lookup", which is the real issue here.

By the way, a very similar question has been discussed on this forum
just a few days ago, under the subject 'Rationale for "this->" in
template derived classes?'.

> I would have expected the call to f() in g() to be OK. However, it isn't
> for g++ 3.4:

g++ is right. An unqualified non-dependent name must be bound at the
point of definition (phase one) and the base template class A<T> is not
searched because its definition is still unknown. Yes, it's unknown!
Even if you just gave the definition for the generic template of A<T>,
there may be specialization not yet known at the point of definition of
B<T>. See the aforementioned discussion thread for details.

> checker.cc: In member function `void B<T>::g()':
> checker.cc:14: error: there are no arguments to `f' that depend on a
> template parameter, so a declaration of `f' must be available

see? as there are no arguments to f, the compiler is saying that it
can't use ADL.

> Replacing f() with A<T>::f() will fix it.

Sure, as the name is now qualified and dependent on T, it will be bound
at the point of instantiation (phase two). In phase two, the compiler
knows the exact type that replaces T and so it can select the right
specialization of A<T> (specializing A<T> after this point makes the
program ill-formed).

Another, more elegant, way to make the name dependent is by writing
this->f().

Alberto

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Fri, 30 Apr 2004 03:15:37 +0000 (UTC)
Raw View
Derek Long wrote:
> I have just been experimenting with g++ 3.4 and code that I thought was
> compliant has raised compiler problems. Basically, if we have the
> following code:
<snip>
> template<typename T>
> class A {
> public:
>  T f() {return T();};
> };
>
> template<typename T>
> class B : public A<T> {
> public:
>  void g() {cout << f() << "\n";};
> };
<snip>
> I would have expected the call to f() in g() to be OK. However, it isn't
> for g++ 3.4:
>
> checker.cc: In member function `void B<T>::g()':
> checker.cc:14: error: there are no arguments to `f' that depend on a
> template parameter, so a declaration of `f' must be available
> checker.cc:14: error: (if you use `-fpermissive', G++ will accept your
> code, but allowing the use of an undeclared name is deprecated)
>
> Replacing f() with A<T>::f() will fix it. But is it a valid error, or is
>   g++ 3.4 wrong?

This has nothing to do with ADL.  It is a result of the switch to
two-phase name lookup required by the standard.

The problem results from these rules:
- Names used in templates are classified as dependent or non-dependent
  (on the template parameters).  Non-dependent names are looked up
  when the template is defined whereas dependent names are looked up
  when the template is instantiated.  (Old template implementations
  defer all name lookup until instaniation.)
- Non-dependent name lookup does not look in dependent base classes
  because their definitions are not necessarily available.  (There
  may be specialisations to follow.)
- Unqualified names are generally classified as non-dependent.

Where a name is intended to be looked up in a dependent base class,
it should be made dependent by qualifying it with "this->" or with
the scope operator and base class name.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nesotto@cs.auc.dk ("Thorsten Ottosen")
Date: Fri, 30 Apr 2004 05:47:17 +0000 (UTC)
Raw View
"Derek Long" <Derek.Long@cis.strath.ac.uk> wrote in message
news:408f80a9$1@nntphost.cis.strath.ac.uk...

[snip]

<typename T>
| class B : public A<T> {
| public:
| void g() {cout << f() << "\n";};
| };
|
| int main()
| {
| B<int> b;
| b.g();
| };
|
|
| I would have expected the call to f() in g() to be OK. However, it isn't
| for g++ 3.4:

It has to do with two-phase lookup. When you have a dependent base class
(a class which depends on a template parameter), you need to say either

1. A<T>::f() // no virtual dispatch
2. this->f(); // virtual dispatch if f() is vitual

br

Thorsten


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]