(I've sent the same questions to gcc@xxxxxxxxxxx, but probably this is a
more proper place for such questions. Thanks!)
I am confused on the different outcomes from g++3.4.3 and 4.2.4 on the
three attached C++ programs. Somehow g++ 3.4.3 can compile all of them, but
g++ 4.2.4 can only compile the first one. I probably abused the template
inline functions in a bad way, but anyway could someone help to explain
what I did wrong?
===== Case 1 =====
template <class T>
inline T f (T i) {
T j = i - 1;
return g(&j) + i;
}
template <class T>
inline T g (T* i) {
if (*i == 0) return 0;
return f(*i);
}
=====
Both g++ 3.4.3 and 4.2.4 know where to find g() while instantiate f().
===== Case 2 (change the name of g() to f()) =====
template <class T>
inline T f (T i) {
T j = i - 1;
return f(&j) + i;
}
template <class T>
inline T f (T* i) {
if (*i == 0) return 0;
return f(*i);
}
=====
g++ 4.2.4 doesn't seem to know about the 2nd template function of f(), and
keeps coerce int* into int:
fwd-template-inline2.cpp: In function T f(T) [with T = int]:
fwd-template-inline2.cpp:14: instantiated from here
fwd-template-inline2.cpp:4: error: invalid conversion from int* to int
fwd-template-inline2.cpp: In function T f(T) [with T = int*]:
fwd-template-inline2.cpp:4: instantiated from T f(T) [with T = int]
fwd-template-inline2.cpp:14: instantiated from here
fwd-template-inline2.cpp:4: error: invalid operands of types int** and int*
to binary operator+
fwd-template-inline2.cpp: In function T f(T) [with T = int**]:
fwd-template-inline2.cpp:4: instantiated from T f(T) [with T = int*]
fwd-template-inline2.cpp:4: instantiated from T f(T) [with T = int]
fwd-template-inline2.cpp:14: instantiated from here
fwd-template-inline2.cpp:4: error: invalid operands of types int*** and
int** to binary operator+
fwd-template-inline2.cpp: In function T f(T) [with T = int***]:
fwd-template-inline2.cpp:4: instantiated from T f(T) [with T = int**]
fwd-template-inline2.cpp:4: instantiated from T f(T) [with T = int*]
fwd-template-inline2.cpp:4: instantiated from T f(T) [with T = int]
fwd-template-inline2.cpp:14: instantiated from here
...
===== Case 3 ====
#include <vector>
template <class T>
inline size_t f (const T* x) {
if (x) return f(*x);
return 0;
}
template <class T>
inline size_t f (const std::vector<T>& x) {
return x.size();
}
=====
Similar to case 2, g++ 4.2.4 doesn't see the 2nd definition, and complains
about no matching function.
fwd-template-inline3.cpp: In function size_t f(const T*) [with T =
std::vector<double, std::allocator<double> >]:
fwd-template-inline3.cpp:16: instantiated from here
fwd-template-inline3.cpp:5: error: no matching function for call to f(const
std::vector<double, std::allocator<double> >&)
I understand that adding a forward declaration of the 2nd definition, like
the line below, would solve the problem of Case 3 (and Case 2 as well).
template <class T>
inline size_t f (const std::vector<T>&);
However, I am not sure if the compiler would still honor the "inline" hint.
Actually, I don't even know if including "inline" in the forward
declaration make any sense, since forward declaration means the definition
is not available at this moment.
And anyway, g++ 3.4.3 is quite happy with all cases, so it is confusing
which g++ version actually does the correct thing.
Any opinions would be highly appreciated! Thanks!
--Ling
===== attached programs =====
template <class T>
inline T f (T i) {
T j = i - 1;
return g(&j) + i;
}
template <class T>
inline T g (T* i) {
if (*i == 0) return 0;
return f(*i);
}
int main () {
return f(3);
}
template <class T>
inline T f (T i) {
T j = i - 1;
return f(&j) + i;
}
template <class T>
inline T f (T* i) {
if (*i == 0) return 0;
return f(*i);
}
int main () {
return f(3);
}
#include <vector>
template <class T>
inline size_t f (const T* x) {
if (x) return f(*x);
return 0;
}
template <class T>
inline size_t f (const std::vector<T>& x) {
return x.size();
}
int main () {
std::vector<double> vd(10);
return f(&vd);
}