4

Why doesn't the compiler find a match for read1? I don't see the difference between read1 and read2; is there a limitation for nested typedef templates like the one in the Foo class?

template<typename T>
class Handle{};

class Foo{
public:
    typedef Handle<Foo> Handle;
};


template<typename T>
void read1(typename T::Handle){}

template<typename T>
void read2(Handle<T>){}


int main(int argc, char** argv)
{
    Foo::Handle f1;    
    read1(f1);

    Foo::Handle f2;
    read2(f2);
}

G++ compiler output, (G++ 4.4.5)

g++ -c -I.  main1.cpp 
main1.cpp: In function ‘int main(int, char**)’:
main1.cpp:37: error: no matching function for call to ‘read1(Handle<Foo>&)’
Xeo
  • 129,499
  • 52
  • 291
  • 397
José
  • 3,041
  • 8
  • 37
  • 58
  • I removed the redundant `Internal` namespace, keep examples concise. – Xeo Dec 23 '11 at 00:36
  • With G++ 4.4.5 your edit break the code, `g++ -c main.cpp main.cpp:8: error: declaration of ‘typedef class Handle Foo::Handle’ main.cpp:3: error: changes meaning of ‘Handle’ from ‘class Handle’ main.cpp: In function ‘int main(int, char**)’: main.cpp:27: error: no matching function for call to ‘read1(Handle&)’` – José Dec 23 '11 at 01:40

2 Answers2

4
Foo::Handle f1;    
read1(f1);

The type being passed to read1 is Handle<Foo>, not Foo.

Templates are not inheritance. Handle<Foo> is a distinct class that is not a Foo, so there is no Handle<Foo>::Handle.

Gerald
  • 23,011
  • 10
  • 73
  • 102
3
template<typename T>
void read1(typename T::Handle)
{
}

First, you will never be able to call this function without providing an explicit template parameter like read1<Foo>(f1). Read up on SFINAE.

Second, how should the compiler ever find out what T is? It would have to test all nested typedefs of all possible classes you could possibly ever write. Sounds impossible? It is.

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 2
    It doesn't have to test every class you could possibly write; it need only test those classes defined at the point of the read1 call. Possible (easy even, compared to some things required of the compiler to handle templates), but not done per the standard. – Chris Dodd Dec 23 '11 at 01:31
  • Why can find the argument like it does for read2? It just need to test Foo there aren't other types – José Dec 23 '11 at 01:37
  • It doesn't just have to test all classes defined at the point, but also all possible template instantiations (might be possible in template form though). But how would it resolve ambiguities? Normaly the programmer would have to fix those, but in this case some completely unrelated code change (different namespace and all) can lead to an ambiguity there, so having the programmer fix those isn't really an option. @José: It might only have to test foo in this simple example, but most scnearious are more complicated and language features which don't work most of the times aren't all that popular – Grizzly Dec 23 '11 at 02:24