This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/17344] completely wacky error with matching template template classes and default arguments


------- Additional Comments From bangerth at dealii dot org  2004-09-16 16:17 -------
Alright, this is completely bizarre: 
------------------------ 
template <class> struct intTraits {}; 
 
template<> struct intTraits<int> { 
    static const int i = 0; 
}; 
 
template <typename T> 
struct injector { 
    friend void foo (T) {}; 
}; 
 
template<typename E, E i = intTraits<E>::i> 
struct bitset : injector<bitset<E, i> > {}; 
 
struct S: injector<S> { 
    template <template <typename> class X> S(X<void>); 
}; 
 
void foo() { 
  bitset<int> bed; 
  foo(bed); 
} 
-------------------------- 
What happens is this: both struct bitset and struct S derive from  
struct injector, so that after instantiating bitset<int> we have the 
following two functions foo() in the global namespace: 
  void foo(bitset<int,0>); 
  void foo(S); 
Now, when we get to the line where we call foo(), the compiler checks out 
all members of the overload set, i.e. the two functions above. It could 
realize that it should simply call the first one because the argument is 
of type bitset<int,0>, but it also tries the second one and finds out 
the following: 
  - the argument bitset<int,0> isn't an exact match to the type "S" 
    needed for the second foo() function 
  - but, lo and behold, they may be convertible as S has a templated 
    copy constructor. So it tries whether it can match X<void> against 
    bitset<int> (remember that gcc has an extension that allows to 
    treat template classes with two template arguments of which the 
    second one has a default value just as a template class with only 
    one argument).  
  - to do that, it matches X against bitset, but then it has to 
    figure out the value of the second argument of bitset using the 
    default argument, and that means that it has to look up 
      intTraits<void> 
  - that doesn't exist, so it realizes that the second template argument 
    has an invalid valid, and thus we get this obscure error message: 
    g/x> /home/bangerth/bin/gcc-4.0-pre/bin/c++ -c x.cc 
    x.cc: In function `void foo()': 
    x.cc:21: error: template argument 2 is invalid 
 
This is certainly one of the most amusing PRs I've seen in a while :-) 
 
Note that gcc2.95 through 3.3.x had slightly better error messages: 
g/x> /home/bangerth/bin/gcc-2*/bin/c++ -c x.cc 
x.cc: In function `void foo()': 
x.cc:21: `i' is not a member of type `intTraits<void>' 
x.cc:21: template argument 2 is invalid 
 
At least it hinted at intTraits<void> although it is of course completely 
nonobvious why it is even looking at that class. 
 
W. 

-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
     Ever Confirmed|                            |1
   Last reconfirmed|0000-00-00 00:00:00         |2004-09-16 16:17:50
               date|                            |
            Summary|spurious error              |completely wacky error with
                   |                            |matching template template
                   |                            |classes and default
                   |                            |arguments


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17344


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]