0

I'm working on my own math library, and I have a couple of non-member functions in the namespace I'm using for the library ("cml", like it matters much). Anyway, the library (which I'm building statically as a .a/.lib file) compiles just fine, but when I go to use the library in a test program, I get an error that the functions are undefined references.

This is header (func.h) file:

namespace cml
{

template <typename T>
T toRadians(T val);
template <typename T>
T toDegrees(T val);

template <typename T>
T fastSqrt(T val);
template <typename T>
T fastInverseSqrt(T val);

}

And this is the func.cpp file:

#include <CML/func.h>

#include <cmath>
#include <math.h>
#include <limits>
#include <cassert>

namespace cml
{

template <typename T>
T toRadians(T val)
{
    static_assert(std::numeric_limits<T>::is_iec559, "toRadians() requires the template parameters to be floating points.");

    return val * MATH_PI / 180;
}

template <typename T>
T toDegrees(T val)
{
    static_assert(std::numeric_limits<T>::is_iec559, "toDegrees() requires the template parameters to be floating points.");

    return val * 180 / MATH_PI;
}

template <typename T>
T fastSqrt(T val)
{
    static_assert(std::numeric_limits<T>::is_iec559, "fastSqrt() requires the template parameters to be floating points.");

    return T(1) / fastInverseSqrt(val);
}

template <typename T>
T fastInverseSqrt(T val)
{
    static_assert(std::numeric_limits<T>::is_iec559, "fastInverseSqrt() requires the template parameters to be floating points.");

    T tmp = val;
    T half = val * T(0.5);
    uint32* p = reinterpret_cast<uint32*>(const_cast<T*>(&val));
    uint32 i = 0x5f3759df - (*p >> 1);
    T* ptmp = reinterpret_cast<T*>(&i);
    tmp = *ptmp;
    tmp = tmp * (T(1.5) - half * tmp * tmp);
#if defined(CML_ACCURATE_FUNC) // If more accuracy is requested, run Newton's Method one more time
    tmp = tmp * (T(1.5) - half * tmp * tmp);
#endif // defined
    return tmp;
}

}

I am getting the error for all four of the functions. I am using the latest version of Code::Blocks, with GCC on Windows8. I am compiling for Win32. I've tried different suggestions I've found like marking the functions extern, but it doesn't seem to fix it. I'm sure it's something simple I'm missing, and if that is the case a second pair of eyes might help.

The error exactly: undefined reference tofloat cml::toRadians(float)'`

sm81095
  • 290
  • 1
  • 6
  • 18
  • What **exactly** does the error message say? – Soren Jul 12 '14 at 02:26
  • Wow, can't believe I forgot that, the most important part. I'll add it now. – sm81095 Jul 12 '14 at 02:28
  • 2
    The template functions have to be in the header file -- otherwise they don't expand correctly at compilation time -- just like what @SleuthEye duplicate link says.... – Soren Jul 12 '14 at 02:33

1 Answers1

2

You need to define template functions inside the header file. What I would do is

  1. Rename func.cpp to func.inl, and make sure it is not being compiled with a C++ compiler.
  2. Add the line #include "func.inl" to the bottom of func.h.

Template functions are not compiled like regular functions, but are handled by a later compilation stage (like inline functions).

Luke Worth
  • 570
  • 3
  • 18
  • @SleuthEye's link is worth reading as well. (http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Luke Worth Jul 12 '14 at 03:03
  • @SleuthEye's link is working for me as well. However this also helped with another error I was having. Thanks. – sm81095 Jul 12 '14 at 03:42