考虑以下片段。
class Stream {
template <class T>
void Write(const T& data);
};
class String { };
template <int N>
class Vector { };
template <>
void Stream::Write(const String& data) { }
到目前为止,一切都很好。现在,我想专门设计 Stream::Write
对于 Vector
s与任何N。
template <int N>
void Stream::Write(const Vector<N>& data) { }
但是,这段代码无法编译。error C2244: 'Stream::Write': unable to match function definition to an existing declaration
你能解释一下我的代码有什么问题吗?是不是因为C++不允许部分函数特化?如果是的话,你能告诉我一个不需要修改的替代解决方案吗?Stream
类(因为它属于一个单独的库)。
如果你不能使用函数重载,因为Stream的接口是一成不变的,你有以下三种选择。
写一个单独的函数来实现写。
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);
}
第二种选择,如果你想使用部分模板专用化 就是使用一个漏斗来实现。
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);
}
最后一个选项是编译时的分支 if constexpr
. 这只有在你能使用C++17及以上版本的情况下才能使用,而且你不能使用任何形式的类型推理,所以它不能解决你目前的问题,但可能会对你将来有所帮助。
template <class T>
void Stream::Write(const T& data) {
if constexpr(std::is_same_v<T, String>) {
// String implementation
} else {
// Default implementation
}
}
C++不允许函数模板特殊化,但是,它允许函数重载。你的代码中不是这个问题。根据这个错误,看起来你没有在Stream类中声明那个特殊的函数模板。你的代码应该是这样的。
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);
};
如果你不能修改Stream类 原有的函数模板将接受所有Vector模板的类 在不修改相关类的情况下,你不能创建成员函数重载。