user568099
user568099

Reputation: 13

C++ function specialization

Consider the following snippet:

class Stream {
    template <class T>
    void Write(const T& data);
};

class String { };

template <int N>
class Vector { };

template <>
void Stream::Write(const String& data) { }

Everything works fine so far. Now I'd like to specialize Stream::Write for Vectors with any N:

template <int N>
void Stream::Write(const Vector<N>& data) { }

However, that code fails to compile: error C2244: 'Stream::Write': unable to match function definition to an existing declaration

Can you explain me what is wrong with my code? Is it because C++ doesn't allow partial function specialization? And if so, can you show me an alternative solution without modifying Stream class (as it belongs to a separate library)

Upvotes: 0

Views: 79

Answers (2)

OutOfBound
OutOfBound

Reputation: 2004

If you can not use function overloading, because the interface of Stream is set in stone you have these three options:

Write a seperate function for the implemation of the write:

void write_impl(const String&) {
    // String implementation
}

template <int N>
void write_impl(const Vector<N>&) {
    // Default implementation
}

template <class T>
void Stream::Write(const T& data) {
    write_impl(data);
}

Second option, if you want to use partial template specialisation is using a functor for the implementation:

template <class T>
struct write_impl_t;

template <>
struct write_impl_t<String> {
    void operator()(const String&) {
        // String implementation
    }
};


template <int N>
struct write_impl_t<Vector<N>> {
    void operator()(const Vector<N>&) {
        // Default implementation
    }
};


template <class T>
void Stream::Write(const T& data) {
    write_impl_t()(data);
}

And the last option is compiletime branching with if constexpr. This is only available if you can use C++17 and above and you can not use type deduction of any sort, so it will not solve your current problem but may help you in the future:

template <class T>
void Stream::Write(const T& data) {
    if constexpr(std::is_same_v<T, String>) {
        // String implementation
    } else {
        // Default implementation
    }
}

Upvotes: 0

Azam Bham
Azam Bham

Reputation: 1399

C++ does not allow function template specialisation, however, it does allow function overloading. That is not the issue in your code. Based on the error, it looks like you failed to declare that particular function template within the Stream class. Your code should look like:

class String { };

template <int N>
class Vector { };

class Stream {
    //function template
    template <class T>
    void Write(const T& data);

    //function overload for String class
    void Write(const String& data);

    //function template overload for Vector template
    template<int N>
    void Write(const Vector<N>& data);
};

If you cannot modify the Stream class, the original function template will accept all Vector template classes. You cannot create member function overloads without modifying the class in question.

Upvotes: 1

Related Questions