Name lookup in templates

Peter Doerfler gcc@pdoerfler.com
Tue Aug 1 11:26:00 GMT 2006


Michael Heissmeier wrote:
> Hello,
> 
> 
> the following code snippet compiles under gcc 3.2.3 but fails to do so using
> gcc 4.1.0. It is not clear to me whether this is a problem with gcc or with
> my code. 

FYI, Comeau detects the same error as gcc4.1.0. Given its reputation
this is probably the correct behaviour.

> 
> The compiler tells me that it cannot convert C to an int. It seems that TFunc's
> call to A::func is bound at definition time although this call depends on the
> template parameter. I therefore would expect it to bind during instantiation.
> 
> --------------------------------------------
> 
> namespace A { 
> 
> int func (int c) { return (c + 1); }
> 
> } 
> 
> template <typename Type>
> int TFunc (Type t) { return A::func (t); }
> 
> 
> class C
> {
>   public:
> 
>     int myint;
> };
> 
> 
> namespace A { 
> 
> int func (C c) { return (c.myint + 1); }
> 
> } 
> 
> 
> int main ()
> {
> 
>     C x;
>     x.myint = 2;
> 
>     int y = TFunc (x);
> }
> 
> 
> --------------------------------------------------------
> 
> 
> The reason for this code layout is that the first definition of func 
> and the template reside in a header which should be included in many
> source files.
> 
> The definition of Class C happens in an implementation where 
> namespace A is reopened in order to add an according definition for func.
> 
> It would be nice if there were a solution without getting rid of the 
> namespace which prevents us from having to prefix lots of names.
> 
> Any suggestions are welcome.

My guess why your code doesn't work is that the compiler can't know that
you might be overloading the namespace functions at a later point.
However, if you put the functions in a struct as template member
functions and then specialize them, you'll be fine (You could use a
templated struct and specialize that as well).
Note that this is just my idea of why your version is not allowed. Maybe
someone with more Standard foo can pitch in for a better explanation. I
think I read it before but I can't recall where.

Anyway, the below should solve your problem:

namespace A {

  struct func {
    template <typename Type>
    static int use(Type t);
  };

  template<>
  int func::use<int>(int c) {
    std::cout << "func(int)\n";
    return (c + 1);
  }
}

class C
{
  public:
    int myint;
};

template <typename Type>
int Tfunc (Type t) {
  std::cout << "Tfunc(Type)\n";
  A::func::use(t);
}

namespace A {
  template<>
  int func::use<C>(C c) {
    std::cout << "func(C)\n";
    return (c.myint + 1);
  }
}


int main ()
{
    C x;
    x.myint = 2;
    int y = Tfunc (x);
}


> 
> 
> Michael Heissmeier



More information about the Gcc-help mailing list