0

私は、値を指定された小数点位置と比較する非常に単純なfloat/double比較関数のセットを作ろうとしています。C++テンプレート関数の特殊化?

#include "stdafx.h" 
#include "CppUnitTest.h" 

#include <exception> 

using namespace Microsoft::VisualStudio::CppUnitTestFramework; 

namespace lqpro 
{ 
    namespace /* anonymous */ 
    { 
    template<typename _type> 
    _type myAbs(_type left, _type right) 
    { 
     throw std::exception("lqpro::myAbs() called with non-float type parameter"); 
    } 

    template<> 
    double myAbs(double left, double right) 
    { 
     return fabs(left - right); 
    } 

    template<> 
    float myAbs(float left, float right) 
    { 
     return fabsf(left - right); 
    } 

    template<typename _type> 
    static _type quick_pow10(int n) 
    { 
     static _type pow10[10] = { 
     1.0, 10.0, 100.0, 1000.0, 10000.0, 
     100000.0, 1000000.0, 10000000.0, 
     100000000.0, 1000000000.0 
     }; 

     return pow10[n]; 
    } 

    } // anonymous... 

    template<typename _type> 
    bool floatCompare(_type left, _type right, const int decimals=5) 
    { 
    _type _mul = quick_pow10<_type>(decimals); 

    _type _left = left * _mul; 
    _type _right = right * _mul; 

    _type _diff = myAbs(left - right); 
    if (static_cast<int>(_diff) == 0) 
     return true; 

    return false; 
    } 

    template<> 
    bool floatCompare<>(float left, float right, const int decimals); 

    template<> 
    bool floatCompare<>(double left, double right, const int decimals); 

} // lqpro... 

namespace lqpro_tests 
{  
    TEST_CLASS(FloatCompare_tests) 
    { 
    public: 

     TEST_METHOD(ComparingFloatsZeroToOneReturnsFalse) 
     { 
     Assert::IsFalse(lqpro::floatCompare(0.0f, 1.0f, 5)); 
     } 

    }; 
} // lqpro_tests... 

私の問題は、これは私のためにコンパイルされないということです。しようとすると、それは次のエラーを取得する...

1>FloatCompare_tests.cpp 
1> Creating library D:\proj\LottoQuestPro\LottoQuestPro_Solution\Debug\LQPro_tests.lib and object D:\proj\LottoQuestPro\LottoQuestPro_Solution\Debug\LQPro_tests.exp 
1>FloatCompare_tests.obj : error LNK2019: unresolved external symbol "bool __cdecl lqpro::floatCompare<float>(float,float,int)" ([email protected]@[email protected]@[email protected]) referenced in function "public: void __thiscall lqpro_tests::FloatCompare_tests::ComparingFloatsZeroToOneReturnsFalse(void)" ([email protected][email protected][email protected]@QAEXXZ) 
1>D:\proj\LottoQuestPro\LottoQuestPro_Solution\Debug\LQPro_tests.dll : fatal error LNK1120: 1 unresolved externals 
1>Done building project "LQPro_tests.vcxproj" -- FAILED. 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

は、私はちょうど、二重に一度フロート用と1回、2回floatCompare()関数を書くことができますが、私は、コードを複製しないことを好むだろうと仮定します。 ..

私は間違っていますか?

おかげ

+0

パラメータが浮動しない場合、std :: enable_ifを使用してテンプレートのコンパイルを停止することができます。 myAbsにテンプレートパラメータとして次を追加します。 "typename = typename std :: enable_if :: value> :: type"それはtype_traitsにあります。 – Robinson

+0

存在しないオーバーロードを呼び出すときにコンパイル時エラーが発生するのではなく、「非float型パラメータで呼び出された」例外をスローする特別な理由はありますか?オーバーロードの代わりに関数の特殊化を使用する特別な理由はありますか?そして最後に、 'floatCompare'は、不要な未定義の特殊化を取り除いた場合と同じように機能します。 – WindyFields

+0

'myAbs(左 - 右)'はあなたが 'myAbs(左、右)'を意味しました – WindyFields

答えて

1

専門分野(あなたはを定義しないこと)

template<> 
bool floatCompare<>(float left, float right, const int decimals); 

template<> 
bool floatCompare<>(double left, double right, const int decimals); 

あなたがそれらを明示的にインスタンス化する場合、それは希望を宣言しますbe

template 
bool floatCompare<float>(float left, float right, const int decimals); 

template 
bool floatCompare<double>(double left, double right, const int decimals); 

ただし、すべての用途が定義にアクセスできるため、完全に除外することもできますe行。

+0

私は専門化しなければならないと思っていたし、そうでなければfloatCompare (...)を私のコードを通して持っていなければならなかった。ありがとう – jump

0

あなたはイプシロンとの比較、すなわち、いくつかの指定された精度の範囲内の数値を比較しようとしているように見えます。これは私がそれを行うために使用する機能です。

#include <iostream>  
#include <cmath> 

template <typename T0, 
      std::enable_if_t<std::is_floating_point<T0>::value>* = nullptr> 
bool Equal(T0 a, T0 b, T0 epsilon) 
{  
    return std::abs(a - b) <= epsilon; 
} 

int main() 
{ 
    if (Equal(0.1, 0.15, 0.1)) 
    { 
     std::cout << "They are equal to within 0.1";  
    } 
    else 
    { 
     std::cout << "They are not equal to within 0.1"; 
    } 
} 
関連する問題