This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/17344] completely wacky error with matching template template classes and default arguments
- From: "bangerth at dealii dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 16 Sep 2004 16:17:53 -0000
- Subject: [Bug c++/17344] completely wacky error with matching template template classes and default arguments
- References: <20040907100712.17344.igodard@pacbell.net>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- 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