Reputation: 13
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 Vector
s 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
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
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