M
mattias.nissler
Hi!
Here is a problem I ran into at work. The following example doesn't
compile on gcc-4.1:
struct cons_end {};
template<typename U,typename V> struct cons {
U elem;
V tail;
};
template<typename U, typename V>
void foo4(U elem, V tail)
{
::foo4(tail.elem,tail.tail);
}
template<typename U>
void foo4(U elem, cons_end tail)
{
}
int main()
{
typedef cons<int,cons<int,cons_end> > tList;
tList list;
foo4(list.elem,list.tail);
}
The problem occurs in the first call to foo4 [U = int, V = cons<int,
cons_end>]. Now the compiler needs to resolve the nested call to (the
overloaded) foo4 given parameters of type int and cons_end. However,
not the template<typename U> foo4(U, cons_end) is selected, but again
the generic version, leading to the following error:
test1.cpp: In function 'void foo4(U, V) [with U = int, V = cons_end]':
test1.cpp:22: instantiated from 'void foo4(U, V) [with U = int, V =
cons<int, cons_end>]'
test1.cpp:58: instantiated from here
test1.cpp:22: error: 'struct cons_end' has no member named 'elem'
test1.cpp:22: error: 'struct cons_end' has no member named 'tail'
If I change the order of the definitions like so...
struct cons_end {};
template<typename U,typename V> struct cons {
U elem;
V tail;
};
/* N.B. THE TWO VERSIONS OF FOO4() NOW IN DIFFERENT ORDER */
template<typename U>
void foo4(U elem, cons_end tail)
{
}
template<typename U, typename V>
void foo4(U elem, V tail)
{
::foo4(tail.elem,tail.tail);
}
int main()
{
typedef cons<int,cons<int,cons_end> > tList;
tList list;
foo4(list.elem,list.tail);
}
.... the code compiles, the cons_end version of foo4 is selected.
So my question now is: Is this correct behaviour or not? What does the
standard say? If the first version is wrong, why exactly?
Thanks,
Mattias
Here is a problem I ran into at work. The following example doesn't
compile on gcc-4.1:
struct cons_end {};
template<typename U,typename V> struct cons {
U elem;
V tail;
};
template<typename U, typename V>
void foo4(U elem, V tail)
{
::foo4(tail.elem,tail.tail);
}
template<typename U>
void foo4(U elem, cons_end tail)
{
}
int main()
{
typedef cons<int,cons<int,cons_end> > tList;
tList list;
foo4(list.elem,list.tail);
}
The problem occurs in the first call to foo4 [U = int, V = cons<int,
cons_end>]. Now the compiler needs to resolve the nested call to (the
overloaded) foo4 given parameters of type int and cons_end. However,
not the template<typename U> foo4(U, cons_end) is selected, but again
the generic version, leading to the following error:
test1.cpp: In function 'void foo4(U, V) [with U = int, V = cons_end]':
test1.cpp:22: instantiated from 'void foo4(U, V) [with U = int, V =
cons<int, cons_end>]'
test1.cpp:58: instantiated from here
test1.cpp:22: error: 'struct cons_end' has no member named 'elem'
test1.cpp:22: error: 'struct cons_end' has no member named 'tail'
If I change the order of the definitions like so...
struct cons_end {};
template<typename U,typename V> struct cons {
U elem;
V tail;
};
/* N.B. THE TWO VERSIONS OF FOO4() NOW IN DIFFERENT ORDER */
template<typename U>
void foo4(U elem, cons_end tail)
{
}
template<typename U, typename V>
void foo4(U elem, V tail)
{
::foo4(tail.elem,tail.tail);
}
int main()
{
typedef cons<int,cons<int,cons_end> > tList;
tList list;
foo4(list.elem,list.tail);
}
.... the code compiles, the cons_end version of foo4 is selected.
So my question now is: Is this correct behaviour or not? What does the
standard say? If the first version is wrong, why exactly?
Thanks,
Mattias