user819640 user819640 - 16 days ago 4x
C++ Question

Template Specialization of class method. "Function template already defined"

I've seen lots of SO questions about specialization in the context of methods, but not functions belonging to classes. I'm having a hard time translating the knowledge passed on from those questions to my problem here.

I'm mucking around with a class I created in the past to learn and I would like to have a specialization for arithmetic types.

template <typename T>
class Vector3
T x;
T y;
T z;

operator std::string() const;

This is the specialization I am trying to do:

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();

However when I try to compile, I get

error C2995: 'Vector3::operator std::string(void) const': function
template has already been defined

When I google this, it is usually cases where people have defined their class/method in the CPP file as well as the header file. As I only do this in the header file, I can only assume the enable_if is not correct. When I look at other examples, they just do specialization on , , but I'd like to use the is_arithmitic way.

What am I doing wrong? Thanks in advance


The default here:

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

doesn't matter at all, there's no deduction going on at this point, and T is already defined. It's legal, but it's just noise.

Now, you can't partially specialize a member function in a class template either, but we can dispatch on traits:

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

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

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