views:

129

answers:

1

Here's some simplified code to demonstrate the problem I have.

I have a template function for which I only wish to compile certain fixed instantiations.

The function declarations are:

// *** template.h ***
int square (int x);
double square (double x);

The definitions are:

// *** template.cpp ***
#include "template.h"

// (template definition unusually in a code rather than header file)
template <typename T>
T square (T x)
{
    return x*x;
}

// explicit instantiations
template int square (int x);
template float square (float x);

And, an example use is:

// *** main.cpp ***

#include <iostream>
using namespace std;

#include "template.h"

int main (void)
{
    cout << square(2) << endl;
    cout << square(2.5) << endl;
}

An attempt to compile this results in a link errors, roughly:

main.obj : unresolved external symbol "int square(int)" referenced in function main

I understand what the problem is: the function signatures of my explicit template instantiations do not match those in the header file.

What is the syntax for the (forward) declaration of the explicit template instantiations please? I do not wish to forward declare the template definition, or to move the template definition into a header file.

For what it's worth, I do have a workaround, which is to use wrapper functions, adding the following to the above files:

// *** template.cpp ***

// ...

// wrap them [optionally also inline the templates]
int square (int x) { return square<> (x); }
double square (double x) { return square<> (x); }

That compiles and works as expected. However, this seems like a hack to me. There should be something more elegant than this available in C++ and template syntax.

Any help or hints would be much appreciated.

+2  A: 

You need to declare the function template in your header:

template <typename T>
T square(T x);

As you have it now, you declare two nontemplate functions in the header, which are never defined.

James McNellis
but that would suggest that you have more types avail, not only double and int
Ronny
@Ronny: If you tried to instantiate the template with any types other than those for which you provided explicit instantiations in the source file, compilation would fail. If it's not obvious from the declaration, it would be a good idea to document the function template to detail with which types it can be instantiated.
James McNellis
How does a different source file(main.cpp) + the header know of the explicit instantiations? While linking you would get an error - a not very helpful one probably.
Ronny
You can define the template function with a descriptive static assert - that way errors are not delayed until the linking phase.
Georg Fritzsche
Thanks for the comments so far, but please note that my question was not about template functions generally, but specifically about explicit template function instantiation. (As an example, although not relevant in my case, such functions might be provided in a library, but not called; explicit instantiation forces the compiler to generate the required code.) I do not wish to declare the template in the header, because the template is only defined in a specific source file (it is "pseudo-private").
Rhubbarb
@gf: could you expand? Do you know of a good link (or book) describing that technique?
Rhubbarb
@rhubbarb: I am not quite sure what you are trying to accomplish. If you do not want to declare the function template in the header, your only option is to use nontemplate wrapper functions defined in the source file. @gf: The function template can only have one definition, though (barring the use of SFINAE, which would be messier than other alternatives in this situation). The OP wants the definition to be in the source file, not in the header, so I'm not quite sure how a static assert would work for that (perhaps I'm missing something?)
James McNellis
For the record: The "static assert" concept mentioned by gf is available in Boost. See, for example, http://www.boost.org/doc/libs/1_42_0/doc/html/boost_staticassert.html, or the book "Beyond the C++ Standard Library" by Björn Karlsson [ISBN 9780321133540].
Rhubbarb
@James: your statement in your follow-up comment that "[my] only option is to use nontemplate wrapper functions defined in the source file" appears to answer my question, although in the negative. If you submit an answer to that effect, I'll happily accept it. (I don't wish to accept the original answer statement, which whilst useful an correct did not get at the crux of my question.) Please don't edit your original answer, as that may be useful to others as it stands. Thanks.
Rhubbarb