0

I am trying to forward declare a bunch of template functions, which are present in the header file SelectionSort.h trying to learn about the working of function pointers.

I tried reading this question still not sure how it fits my problem

Here are the files -

SelectionSort.h

#ifndef SELECTIONSORT_H
#define SELECTIONSORT_H

template<typename T, size_t N>
void selection_sort(T (&arr)[N], bool (*comparer_func)(T, T));

template<typename T>
bool ascending_comparer(T, T);

template<typename T>
bool descending_comparer(T, T);

template<typename T, size_t N>
void print_array(const T (&arr)[N]);
#endif

SelectionSort.cpp

#include <algorithm>
#include <iostream>
#include "SelectionSort.h"

template<typename T>
bool ascending_comparer(T x, T y)
{
    return x > y;
}

template<typename T>
bool descending_comparer(T x, T y)
{
    return x < y;
}

template<typename T, size_t N>
void selection_sort(T (&arr)[N], bool (*comparer_func)(T, T))
{
    for (size_t i = 0; i < N - 1; i++)
    {
        size_t smallest = i;
        for (size_t j = i + 1; j < N; j++)
        {
            if (comparer_func(arr[smallest], arr[j]))
            {
                smallest = j;
            }
        }

        if (smallest != i)
        {
            std::swap<T>(arr[i], arr[smallest]);
        }
    }
}

template<typename T, size_t N>
void print_array(const T (&arr)[N])
{
    for (const auto& item : arr)
    {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}

main.cpp

#include <iostream>
#include <iterator>
#include "SelectionSort.h"

int main(int argc, char** argv)
{
    int arr[] = { 5, 4, 3, 2, 1, 0, -1 };
    constexpr size_t len = std::size(arr);

    selection_sort<int, len>(arr, ascending_comparer);
    print_array<int, len>(arr);

    return 0;
}

So I am getting the linker error LNK2019 only when I try to forward reference them via a header file but it compiles successfully without any error too, not sure what is wrong here -

1>FunctionPointers.obj : error LNK2019: unresolved external symbol "void __cdecl selection_sort<int,7>(int (&)[7],bool (__cdecl*)(int,int))" (??$selection_sort@H$06@@YAXAAY06HP6A_NHH@Z@Z) referenced in function _main
1>FunctionPointers.obj : error LNK2019: unresolved external symbol "bool __cdecl ascending_comparer<int>(int,int)" (??$ascending_comparer@H@@YA_NHH@Z) referenced in function _main
1>FunctionPointers.obj : error LNK2019: unresolved external symbol "void __cdecl print_array<int,7>(int const (&)[7])" (??$print_array@H$06@@YAXAAY06$$CBH@Z) referenced in function _main

The above solution works if I straightaway copy the contents of SelectionSort.cpp into main.cpp.

Any ideas for obvious mistakes I am making?

Kunal Mukherjee
  • 5,775
  • 3
  • 25
  • 53
  • The dupe covers this very well. All your template *definitions* need to be visible at the call site. Compiling them separately is useless, as they won't get instantiated. Which part are you unclear about specifically? – cigien Sep 14 '20 at 18:13
  • @cigien So tl:dr; it means that I cant place the defintions inside a different source file ? – Kunal Mukherjee Sep 14 '20 at 18:14
  • 2
    I strongly recommend reading the dupe thoroughly. It's good stuff. And yes, *just* defining them in a source file won't work. (Unless you instantiate them explicitly, or include the source file). – cigien Sep 14 '20 at 18:17
  • 1
    Thanks @cigien will go through [`this FAQ`](https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl) – Kunal Mukherjee Sep 14 '20 at 18:22

0 Answers0