This is the mail archive of the gcc-help@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]

Questions on recursive template inline functions


(I've sent the same questions to gcc@gcc.gnu.org, 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);
}


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