我定义了以下功能:
template <typename T> buffer_t &operator<<(buffer_t &buffer, T data);
template <> buffer_t &operator<<(buffer_t &buffer, const char *data);
template <> buffer_t &operator<<(buffer_t &buffer, const Glib::ustring &data);
我打电话的时候:
buffer << Glib::ustring("hello");
编译器使用通用模板定义而不是Glib :: ustring的专门化。
我在这里做错了什么?
答案 0 :(得分:5)
您有功能模板,并且您想执行模板参数扣除。为此,您的函数调用将与模板化函数参数T data
进行匹配。我相信14.8.2.4适用于你的专业化的部分排序,其中P
是模板参数,A
是实际参数的类型;重点是我的):
在完成部分排序之前,会对用于部分的类型执行某些转换 排序:
- 如果
P
是引用类型,P
将被引用的类型替换。- 如果
A
是参考类型,则A
将替换为所引用的类型。
因此,由于你的参数类型是A = Glib::ustring
,那么这不像主模板那样匹配专业化const Glib::ustring &
,即使你有一个实际的const-reference ,在部分排序期间,参考被剥离,你最终会得到更糟糕的匹配。
解决此问题的常用方法是使主模板成为const-reference;这也可以绑定到临时对象,因此应该与值参数“一样好”:
template <typename T> buffer_t & operator<<(buffer_t & buffer, T const & data);
// ^^^^^^^^^
答案 1 :(得分:4)
template <typename T> buffer_t &operator<<(buffer_t &buffer, T data);
是主要模板。专业化不是主要模板。编译器在匹配函数时只查找主模板,然后,如果选择模板函数有专门化,则查看这些,如果编译器找到特殊化,则完全匹配参数 - 使用它,否则使用主模板。
template <> buffer_t &operator<<(buffer_t &buffer, const Glib::ustring &data)
此专精化与操作buffer_t << Glib::ustring("s")
不完全匹配,但这与
template <> buffer_t &operator<<(buffer_t &buffer, Glib::ustring data)
我建议你不要使用函数模板专门化,使用重载。
template <typename T> buffer_t &operator<<(buffer_t &buffer, T data);
buffer_t &operator<<(buffer_t &buffer, const char *data);
buffer_t &operator<<(buffer_t &buffer, const Glib::ustring &data);