Шаблонная специализация метода класса. «Шаблон функции уже определен»

#c #templates #template-specialization

#c #шаблоны #шаблон-специализация

Вопрос:

Я видел много вопросов SO о специализации в контексте методов, но не функций, принадлежащих классам. Мне трудно перевести знания, переданные из этих вопросов, в мою проблему здесь.

Я занимаюсь классом, который я создал в прошлом для изучения, и я хотел бы иметь специализацию для арифметических типов.

 template <typename T>
class Vector3
{
public:
    T x;
    T y;
    T z;

public:
    operator std::string() const;
}
  

Это специализация, которую я пытаюсь сделать:

 template<typename T = std::enable_if<std::is_arithmetic<T>::value, T>::type>
inline Vector3<T>::operator std::string() const {

    std::stringstream ss;
    ss << "NOT NUMBER {" << x << ", " << y << ", " << z << "}";

    return ss.str();
}

template<typename T = std::enable_if<!std::is_arithmetic<T>::value, T>::type>
inline Vector3<T>::operator std::string() const {

    std::stringstream ss;
    ss << "NUMBER {" << x << ", " << y << ", " << z << "}";

    return ss.str();
}
  

Однако, когда я пытаюсь скомпилировать, я получаю

ошибка C2995: ‘Vector3::operator std::string(void) const’: шаблон функции уже определен

Когда я гуглю это, обычно это случаи, когда люди определили свой класс / метод в файле CPP, а также в файле заголовка. Поскольку я делаю это только в заголовочном файле, я могу только предположить, что enable_if неверен. Когда я смотрю на другие примеры, они просто специализируются на , , но я бы хотел использовать is_arithmitic способ.

Что я делаю не так? Заранее спасибо

Ответ №1:

Значение по умолчанию здесь:

 template<typename T = XXX>
inline Vector3<T>::operator std::string() const { ... }
  

вообще не имеет значения, на данный момент вычет не выполняется и T уже определен. Это законно, но это просто шум.

Теперь вы также не можете частично специализировать функцию-член в шаблоне класса, но мы можем использовать черты:

 template <class T>
class Vector3 {
public:
    // ...
    operator std::string() const {
        return as_string(std::is_arithmetic<T>{});
    }

private:
    std::string as_string(std::true_type ) {
        // implementation for arithmetic types
    }

    std::string as_string(std::false_type ) {
        // implementation for non-arithmetic types
    }
};
  

Комментарии:

1. Спасибо за ответ. У меня было ощущение, что после всех поисков в Google мне придется использовать отправку тегов… Я посмотрю, есть ли у кого-нибудь другие идеи, прежде чем отмечать это как правильное.

Ответ №2:

Ответ Барри идеален.

Вот некоторые пояснения и предложения:

http://en.cppreference.com/w/cpp/types/enable_if

«Распространенной ошибкой является объявление двух шаблонов функций, которые отличаются только своими аргументами шаблона по умолчанию. Это незаконно, поскольку аргументы шаблона по умолчанию не являются частью подписи шаблона функции, и объявление двух разных шаблонов функций с одинаковой подписью является незаконным «.