2014-12-23 5 views
0

У меня есть этот код в заголовкешаблон C++ специализации с поплавком

class MyMathUtils { 
    template <typename T> static bool IsEqual(const T & val1, const T & val2); 
}; 


template <typename T> 
bool MyMathUtils::IsEqual(const T & val1, const T & val2) 
{ 
    return (val1 == val2); 
}; 

И это в CPP

template <> 
bool MyMathUtils::IsEqual<float>(const float & val1, const float & val2) 
{ 
    if ((val1 - val2) < -EPSILON) return false; 
    if ((val1 - val2) > EPSILON) return false; 
    return true; 
} 

Проблема заключается в том, что компилятор дает мне эту ошибку:

MyMath::MyMathUtils::IsEqual(float const &,float const &)" ([email protected]@[email protected]@@[email protected]) already defined in MyMathUtils.obj; second definition ignored

Но если я использую то же самое, но вместо float я ставлю double, он скомпилирован правильно. Что здесь неверно, что я пропал без вести?

+0

Включить .cpp-файл в конец заголовка –

+0

Является ли спецификация float * only * использована в исходном файле, в котором вы его определили? Я в этом сомневаюсь. И значения, которые вы передаете, поступают из * литеральных констант * (I.e. 'obj-> IsEqual (1.0,1.0)')? это не 'float', если это так; они «двойные». – WhozCraig

+0

@NorahAttkins: Нет, явные специализации подчиняются ODR, поэтому они будут давать подобные ошибки, если вы не объявите их 'inline'. (Кроме того, обращение к файлу, названному как исходный файл, как если бы это был заголовок, было бы довольно запутанным.) –

ответ

1

Вам необходимо объявить специализацию в заголовке.

namespace MyMathUtils { 
    // generic template (shouldn't be static) 
    template <typename T> bool IsEqual(const T & val1, const T & val2); 

    // explicit specialisation 
    template <> bool IsEqual<float>(const float & val1, const float & val2); 

    // alternatively, overloading would be simpler 
    bool IsEqual(float, float); 
}; 

(я взял на себя смелость изменения этого в пространстве имен, а не класс, так как это делает гораздо больше смысла. Если вы действительно хотите, чтобы быть классом по какой-то причине, вы должны объявить специализация в пространстве имен за пределами.)

В противном случае использование его в других единицах перевода приведет к его экземпляру из общего шаблона, поскольку компилятор не знает, что существует явная специализация. Это вызывает несколько определений.

+0

Я уверен, что явные специализации должны быть в области пространства имен. –

+0

@ T.C .: Действительно, они это делают. Я не заметил, что это класс, а не пространство имен (следовательно, мой комментарий, что он не должен быть статическим). –

Смежные вопросы