Template function specialization (MS C++ 2005 Express)

Started by
6 comments, last by Red Ant 18 years, 4 months ago
Hi, I'm having problems trying to write a specialized version of a template function.

// In MathFunctions.h ...
#include <limits>

namespace MathFunctions
{
    /// @brief Template function to test if two values of the same type are equal.
    template < class T > bool testEquality( T valueOne, T valueTwo );

    /// @brief Specialization for doubles.
    template <> bool testEquality( double flValueOne, double flValueTwo );
}

template < class T > bool MathFunctions::testEquality( T valueOne, T valueTwo )
{
    // Normal comparison.
    return valueOne == valueTwo;
}

template <> bool MathFunctions::testEquality( double flValueOne, double flValueTwo )
{
    // Special treatment for floating point values.
    const double flDiff = fabs( flValueOne - flValueTwo );

    if ( flDiff < std::numeric_limits< double >::epsilon() )
    {
        return true;
    }

    return false;
}


The linker throws the following error: main.obj : error LNK2005: "bool __cdecl MathFunctions::testEquality<double>(double,double)" (??$testEquality@O@MathFunctions@@YA_NOO@Z) already defined in MathFunctions.obj ... and I'm clueless what to do about it. I'll admit that template programming is not exactly one of my strengths. =\ Anyhow, does anyone know what I'm doing wrong?
Advertisement
You are missing inclusion guards. Since you are using MSVC, you can add #pragma once to the top of your .h file, or you can use the portable
#ifndef UNIQUENAMEHERE#ifndef SAMEUNIQUENAMEHERE// Code goes here#endif

[edit] As an example for your header:
#ifndef MATHFUNCTIONS_H#define MATHFUNCTIONS_H#include <limits>namespace MathFunctions{    /// @brief Template function to test if two values of the same type are equal.    template < class T > bool testEquality( T valueOne, T valueTwo );    /// @brief Specialization for doubles.    template <> bool testEquality( double flValueOne, double flValueTwo );}template < class T > bool MathFunctions::testEquality( T valueOne, T valueTwo ){    // Normal comparison.    return valueOne == valueTwo;}template <> bool MathFunctions::testEquality( double flValueOne, double flValueTwo ){    // Special treatment for floating point values.    const double flDiff = fabs( flValueOne - flValueTwo );    if ( flDiff < std::numeric_limits< double >::epsilon() )    {        return true;    }    return false;}#endif



jfl.
You will have to hint the compiler about inlining these functions,
e.g.
template < class T > inline bool MathFunctions::testEquality( T valueOne, T valueTwo ){    // Normal comparison.    return valueOne == valueTwo;}template <> inline bool MathFunctions::testEquality( double flValueOne, double flValueTwo ){    // Special treatment for floating point values.    const double flDiff = fabs( flValueOne - flValueTwo );    if ( flDiff < std::numeric_limits< double >::epsilon() )    {        return true;    }    return false;}

@jflanglois Nah, I got the inclusion guards in there alright. Sorry, I didn't post the whole file ... just that parts I deemed relevant.

@darookie Seriously?? Why's that? ... I mean I've used templates before, and I've never had anyone tell me template functions have to be inline to work. I'm not saying you're wrong, but it does seem strange to me.
P.S. If I remove the specialized version, the linker doesn't complain anymore.
The template version doesn't have to be inlined.

The specialised version has to be inlined (or have it's definition placed in a source file) because there's no type substitution going on in the specialised version.

The inline keyword is being used here to tell the compiler about the linkage of the specialised function.
template <> bool testEquality< double >( double flValueOne, double flValueTwo )
Both for the declaration and the definition, to tell the compiler what you're specializing on. (EDIT: well, maybe. According to the final draft standard it's legal not to specify trailing template arguments if they can be deduced from the argument types, but GCC 3.3.1 for one doesn't like doing so, at least not for this example).

Enigma
@Enigma Thanks, but the linker still keeps moaning. :( As for the standard, yeah I saw Stroustrup specialize a function in exactly the same way as I did

template <class T> bool less( T a, T b ) { return a < b; }template <> bool less( const char* a, const char* b ) { return strcmp( a, b ) < 0; }



@Nitage Thanks, I shall try that next.

P.S. Yup that works! Can't say I understand WHY, tho .... =\

This topic is closed to new replies.

Advertisement