3

Let us assume we have a function template which is implemented in the cpp file with help of explicit instantiation like this:

function.h

template<typename T> void function(T val);

function.cpp

#include "function.h"

template<typename T> void function(T val) { /* do something */ }

template void function<double>(double val);

We are now able to call the function in a main file that includes function.h like this:

double val = 1.0;

function(val);

Let us further assume we have a class which is implemented like this:

data.h

class Data
    {
    private:
        double mVal;

    public:
        Data(double val) { mVal = val; }

        operator double () { return mVal; }
    };

The following code results in the linker error LNK2019: unresolved external (Visual Studio 2010):

Data a(1.0);

function(a);

We could use one of the following expressions to supply a to function()

function<double>(a);
function(double(a));
...

but why is it not possible to just call function(a)? Does there exist any other solution to achieve that without explicitly instantiating function() with type Data?

Nex
  • 35
  • 6
  • 1
    So you want the meaning of your program to depend on how much of your program you've already written? If some other TU later instantiates `function`, you want that to magically affect overload resolution in the already compiled TUs? – Kerrek SB May 19 '16 at 17:08
  • That is a good point indeed. I didn't think of the possibility to instantiate function() out of function.cpp. – Nex May 19 '16 at 17:28

2 Answers2

6

why is it not possible to just call function(a)?

It is. You're calling it. But remember that function is declared as:

template<typename T> void function(T val);

so template deduction will deduce function<Data>. The template deduction doesn't know that elsewhere in the code you only have a definition for function<double> - it just does deduction. And function<Data> doesn't have a definition, so it fails to link.

Performing the explicit cast yourself (either function<double>(a) or function(static_cast<double>(a))) would be the best solution in my opinion. Explicit is nice. You could additionally write a separate function with all the overloads you actually support and just forward to the function template:

void fwd_function(double v) { function(v); }
void fwd_function(foo v) { function(v); }
void fwd_function(bar v) { function(v); }

fwd_function(a); // now we call function<double> because fwd_function(double )
                 // is the what we're actually calling
Barry
  • 286,269
  • 29
  • 621
  • 977
1

It is not possible to call function(a), because then T will be of type Data, and not double, even though it has that conversion operator. And because you are not explicitly defining it in the cpp file, you get a linker error.

Here are some solutions you could use:

//Call operator double() explicitly 
function(a.operator double());

//Specify T
function<double>(a);

//Casting
function(static_cast<double>(a));
Rakete1111
  • 47,013
  • 16
  • 123
  • 162