有这样的代码。
const std::string DeviceTypeStrings[] ={ "A", "B", "C", "D", "E" };
enum DeviceTypes { A = 0, B, C, D, E };
template <DeviceTypes T> class DeviceType;
template <DeviceTypes T> std::ostream& operator<< (std::ostream& output, const DeviceType<T>& dev);
template <DeviceTypes T> class DeviceType {
public:
static const int value = T;
static const std::string string;
friend std::ostream & operator<< <>(std::ostream & output, const DeviceType<T> & deviceType );
};
template <DeviceTypes T> const std::string DeviceType<T>::string = DeviceTypeStrings[T];
template <DeviceTypes T> std::ostream & operator<< (std::ostream & output, const DeviceType<T> & deviceType ){
if ( DeviceType<T>::string.find(' ') != std::string::npos ){
return output << "\"" << DeviceType<T>::string << "\"";
} else {
return output << DeviceType<T>::string;
}
}
int main () {
DeviceType<A> myType;
std::cout << myType << std::endl;
return 0;
}
注意有一个“&lt;&gt;”在运营商之后&lt;&lt;在类DeviceType中,“&lt;&gt;”是什么意思?如果可以,为什么必须在那里?
答案 0 :(得分:6)
它只是意味着友元声明引用了函数模板 operator <<
(之前声明的)的特定特化,而不是某些尚未声明的普通非模板函数operator <<
这个朋友声明引用的哪个特化是由参数推导机制决定的,即实际的模板参数是从朋友声明中使用的参数类型隐式派生的。因此,无需明确指定<>
中的模板参数,但仍需要一对空<>
。
换句话说,代码的作者可以明确说明
friend std::ostream & operator<< <T>(std::ostream & output,
const DeviceType<T> & deviceType );
(请注意T
中的明确<T>
)。但是,由于编译器可以自己弄清楚它(从第二个参数的类型派生出来),所以在那里只放置一对空<>
是完全可能的。
现在,如果代码只是说
friend std::ostream & operator<<(std::ostream & output,
const DeviceType<T> & deviceType );
(即根本没有<>
),它会与普通的(非模板)函数operator <<
交朋友,这不是作者想要的。
通过以下简单示例,可以在没有任何好友声明的情况下说明在此好友声明中有效的过载解析功能
void foo(int);
template <typename T> void foo(T);
int main() {
foo(42); // calls non-template function
foo<int>(42); // calls template function, explicit template argument given
foo<>(42); // calls template function, template argument deduced by compiler
}
如果您想告诉编译器您特别想要引用该函数的模板版本,则必须在引用中包含三角括号,即使它们之间没有任何内容。
答案 1 :(得分:3)
编译器在<
之后检查operator<<
是否为模板类的友元函数。它被视为模板参数列表。
答案 2 :(得分:0)
与此link相同。 请参阅“模板专业化”一章。
// template specialization
#include <iostream>
using namespace std;
// class template:
template <class T>
class mycontainer {
T element;
public:
mycontainer (T arg) {element=arg;}
T increase () {return ++element;}
};
// class template specialization:
template <>
class mycontainer <char> {
char element;
public:
mycontainer (char arg) {element=arg;}
char uppercase ()
{
if ((element>='a')&&(element<='z'))
element+='A'-'a';
return element;
}
};
int main () {
mycontainer<int> myint (7);
mycontainer<char> mychar ('j');
cout << myint.increase() << endl;
cout << mychar.uppercase() << endl;
return 0;
}
这就是你如何引用已定义的模板对象(或函数)。