2

I'm discovering some C++11 features and have a problem. I have a member function 'call'

class cscript
{
public:
template <typename ret_t, typename... params>
    bool call(ret_t &ret, const char * name, params... parameters);
....

Implementation:

template <typename ret_t, typename... params>
bool cscript::call(ret_t &ret, const char * name, params... parameters)
{
    ret_t (*func)(params...);
    func = (decltype(func)) tcc_get_symbol(tcc, name);
    if (!func)
        return true;

    ret = func(parameters...);

    return false;
}

When linking the following error is shown:

obj\Release\main.o:main.cpp:(.text.startup+0xcc)||undefined reference to `bool cscript::call<int, int, int>(int&, char const*, int, int)'|

Call example:

script.call(ret, "sum", 2, 3);

Any suggestions on how to make this work?

jogojapan
  • 68,383
  • 11
  • 101
  • 131
The Architect
  • 665
  • 9
  • 22
  • 4
    Is your definition visible at the call site? Templates are header only. – GManNickG Aug 21 '12 at 00:06
  • 2
    Where is the implementation of `cscript::call()` located? Is it in a header file or in an implementation file? – Dietmar Kühl Aug 21 '12 at 00:06
  • 3
    @GManNickG: This isn't entirely true: You can have templates definitions which are not in a header. However, if you do this you need to make sure that all used templates get instantiated. The template definition only needs to be visible when it is used if this should result in an implicit instantiation. – Dietmar Kühl Aug 21 '12 at 00:08
  • What is 'call site'? (My english is not so good) – The Architect Aug 21 '12 at 00:09
  • Implementation located in cscript.cpp, calling 'call()' from 'main()', cscript.h included in main.c... – The Architect Aug 21 '12 at 00:10
  • 4
    Then that's it. Put the implementation in `cscript.h`. – jrok Aug 21 '12 at 00:11
  • 2
    [This thread](http://stackoverflow.com/questions/3749099/why-should-the-implementation-and-the-declaration-of-a-template-class-be-in-the) will help you understand. – jrok Aug 21 '12 at 00:15
  • 1
    @DietmarKühl: Luckily I didn't prefix my sentence with "this is entirely true". :) – GManNickG Aug 21 '12 at 00:41

1 Answers1

5

From the looks of it, the template definition isn't visible when it used. That is, the compiler has no idea what template parameters it needs to pass when it sees the implementation of cscript::call() and it has no idea how the implementation looks like when it is being used. You have two basic options:

  1. Put the definition of cscript::call() into the header so that it is always seen when it is used.
  2. Explicitly instantiate the versions of `csscript::call() you are using.

The latter would look something like below, somewhere after the definition in the implementation file:

template bool cscript::call<int, int, int>(int&, char const*, int, int);

From the looks of it you want to use several different versions of this template and you probably don't want to repeat things. Thus, it is likely that you want to put the definition into the header.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380