0

I've come across an a problem of indirect calling of a function template instance. The struct below defines the type of argument passed indirectly (all of the following code belongs to a single .hpp file):

template<typename individual, typename fitness_value>
struct global_model_worker_state: public base_state {

global_model_worker_state(
        const global_model_worker_state<individual, fitness_value>&) = default;

global_model_worker_state(const shared_props& props,
        const fitness_evaluation_operator<individual, fitness_value>& feo) :
        base_state { props }, fitness_evaluation { feo } {
}

global_model_worker_state& operator=(
        const global_model_worker_state<individual, fitness_value>&) = default;

global_model_worker_state& operator=(
        global_model_worker_state<individual, fitness_value>&&) = default;

fitness_evaluation_operator<individual, fitness_value> fitness_evaluation;
};

The function where reference cannot be resolved:

template<typename individual, typename fitness_value>
behavior global_model_worker(
        stateful_actor<global_model_worker_state<individual, fitness_value>>* self,
        global_model_worker_state<individual, fitness_value> state) {
    self->state = std::move(state);

    return {
        [=](compute_fitness, const individual& ind) {
            // Undefined reference
            return self->state.fitness_evaluation(ind);
        },
    };
}

I then proceed to call spawn which takes the function reference and any number of arguments forwarded to the function.

template<typename individual, typename fitness_value>
void run() {
     ...
     self->spawn(
             global_model_worker<individual, fitness_value>,
             global_model_worker_state<individual, fitness_value> {
                     self->state.props, feo 
             });
 }

Then in a .cpp file:

 run<std::vector<bool>, int>();

The error message returned by the linker is undefined reference to Common::genetic_operator<int, std::vector<bool, std::allocator<bool> > const&>::operator()(std::vector<bool, std::allocator<bool> > const&), which is the instantiation of class template genetic_operator<individual, fitness_value> (of which fitness_evaluation_operator is the alias).

I cannot compile this code since (presumably) the concrete type of fitness_evaluation cannot be inferred though the indirect manner in which global_model_worker<individual, fitness_value> will be called (of which the compiler has no knowledge). My question is, is there a way to suggest circumvent this problem?

  • It's not a case of [Why can templates only be implemented in the header file?](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa) – molbdnilo Nov 17 '18 at 14:20
  • @molbdnilo I'm sorry, should have been clearer about code layout: all of it resides in a .hpp file, I call `run, int>();` in a .cpp one. – MarcinPraski Nov 17 '18 at 14:24
  • 2
    Pretty sure that this is the case of templates not being implemented in a header file. The undefined reference refers to some mysterious template called `generic_operator`, which is nowhere to be seen, but is likely to be the one that's merely declared, and not defined in a header file. Whether something else is an "alias" of it, is immaterial. Instead, this question should be closed due to a failure to provide a [mcve]. – Sam Varshavchik Nov 17 '18 at 14:29

0 Answers0