Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

When I pass a template function as a template parameter of a base class, the linker complains that it cannot link the function :

#include <stdio.h>

template<int I> inline int identity() {return I;}
//template<> inline int identity<10>() {return 20;}

template<int (*fn)()>
class Base {
public:
    int f() {
        return fn();
    }
};

template<int Val>
class Derived : public Base<identity<10> > {
public:
    int f2() {
        return f();
    }
};

int main(int argc, char **argv) {
    Derived<10> o;
    printf("result: %d\n", o.f2());
    return 0;
}

Results in:

$ g++ -o test2 test2.cpp && ./test2 
/tmp/ccahIuzY.o: In function `Base())>::f()':
test2.cpp:(.text._ZN4BaseIXadL_Z8identityILi10EEivEEE1fEv[_ZN4BaseIXadL_Z8identityILi10EEivEEE1fEv]+0xd): undefined reference to `int identity()'
collect2: error: ld returned 1 exit status

If I comment out the specialization, then the code compiles and links as expected. Also, if I inherit from Base<identity<Val> > instead of Base<identity<10> >, the code works as I expect.

Try here: http://coliru.stacked-crooked.com/a/9fd1c3aae847aaf7

What do I miss?

share|improve this question
3  
This problem seems to be a gcc bug: it compiles and links OK using clang and icc. BTW, the name identity() is normally used for transformation where the result is identical to the argument. – Dietmar Kühl 9 hours ago
    
@DietmarKühl Well, identity<X>() returns X. :-) – melpomene 9 hours ago
2  
The workaround: class Derived : public Base<static_cast<int(*)()>(identity<10>) >. live demo – W.F. 9 hours ago
    
@melpomene: sure. However, the template parameter seems to be more something like an index (as in f<sub>i</sub>()) than a function argument. – Dietmar Kühl 9 hours ago
up vote 14 down vote accepted

It seems the problem is a gcc error: the code compiles and links with clang, icc, and the EDG frontend. A potential work-around not changing any of the uses would be the use of a class template identity instead of a function:

template<int I>
struct identity {
    operator int() { return I; }
};

template<typename fn>
class Base {
public:
    int f() {
        return fn();
    }
};
share|improve this answer

lifting it out into a typedef makes it compile i.e.

typedef Base< identity<10> > base10;

not quite sure why doing it straight in the class definition doesn't work.

http://coliru.stacked-crooked.com/a/f00b4f4d1c43c2b0

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.