【转】模板函数的友元声明

摘自《Sun Studio 12: C++ 用户指南》 第 6.7.3 节

 

模板在使用前必须先声明。一个友元声明构成了模板的使用,而非模板的声明。 (A friend declaration constitutes a use of the template, not a declaration of the template. )所以实际的模板声明必须在友元声明之前。例如,编译系统尝试链接以下示例中生成的目标文件时,对未实例化的operator<<函数,会生成一个未定义的错误

 

示例6–2 友元声明问题的示例

// array.h
// generates undefined error for the operator<< function
#ifndef ARRAY_H
#define ARRAY_H
#include <iosfwd>

template<class T> class array {
    int size;
public:
    array();
    friend std::ostream&
        operator<<(std::ostream&, const array<T>&);
};
#endif

// array.cc
#include <stdlib.h>
#include <iostream>

template<class T> array<T>::array() {size = 1024;}

template<class T>
std::ostream&
operator<<(std::ostream& out, const array<T>& rhs)
    {return out << '[' << rhs.size << '[';}

// main.cc
#include <iostream>
#include "array.h"

int main()
{
    std::cout
      << "creating an array of int... " << std::flush;
    array<int> foo;
    std::cout << "done/n";
    std::cout << foo << std::endl;
    return 0;
}

 请注意,因为编译器将以下代码作为普通函数(array类的friend)的声明进行读取(because the compiler reads the following as the declaration of a normal function that is a friend of the array class),所以编译期间不会出现错误消息

friend ostream& operator<<(ostream&, const array<T>&);

 

因为operator<<实际上是模板函数,所 以需要在声明template class array之前提供此“模板函数”(operator<<?)的声明。但是,由于operator<<有一个type为 array<T>的形参(模板类型形参?),因此在声明函数之前,必须声明array<T>。文件array.h必须如下所示:

Because operator<< is really a template function, you need to supply a template declaration for prior to the declaration of template class array. However, because operator<< has a parameter of type array<T>, you must precede the function declaration with a declaration of array<T>. The file array.h must look like this:

 

#ifndef ARRAY_H
#define ARRAY_H
#include <iosfwd>

// the next two lines declare operator<< as a template function
template<class T> class array;
template<class T>
    std::ostream& operator<<(std::ostream&, const array<T>&);

template<class T> class array {
    int size;
public:
    array();
    friend std::ostream&
      operator<< <T> (std::ostream&, const array<T>&);
};
#endif

 

 //-----------------------------------------------------------------------------------

换一个能通过的版本,所有代码都放到同一个文件中。前面那个未通过乃是因为文件之间include有问题,在array.cc中#include "array.h",然后在main.cc中#include "array.cc"即可。

#include <iostream>

// 下面两行将operator<<声明成一个模板函数。因为operator<<实际上是模板函数,
// 所以需要在声明template class array之前提供此“模板函数”(operator<<?)的声明。
template<class T> class array;
template<class T> std::ostream& operator<<(std::ostream&, const array<T>&);

template<class T> class array {
	int size;
public:
	array();
	//请注意,因为编译器将以下一行代码作为普通函数(array 类的 friend)的声明进行读取,
	//所以编译期间不会出现错误消息。但是链接期间会出问题哦 error LNK2019: unresolved external symbol
	//friend std::ostream& operator<< (std::ostream&, const array<T>&);
	//但是,由于operator<<有一个模板形参类型array<T>,因此在声明函数之前,必须声明array<T>。
	friend std::ostream& operator<< <T> (std::ostream&, const array<T>&);

};

template<class T> array<T>::array() {size = 1024;}

template<class T> std::ostream& operator<<(std::ostream& out, const array<T>& rhs)
{return out << '[' << rhs.size << ']';}

int main()
{
	std::cout
		<< "creating an array of int... " << std::flush;
	array<int> foo;
	std::cout << "done/n";
	std::cout << foo << std::endl;
	return 0;
}

 

//------------------------------------------------------------------------------------ 

再换一个所有代码合在一起的版本,使用了using namespace std;

主要是验证下面这段代码的第七行

“template<class T> ostream& operator<<(ostream&, const array<T>&);”

可以被删掉!

#include <iostream>
using namespace std;

// 下面两行将operator<<声明成一个模板函数。因为operator<<实际上是模板函数,
// 所以需要在声明template class array之前提供此“模板函数”(operator<<?)的声明。
template<class T> class array;
//template<class T> ostream& operator<<(ostream&, const array<T>&); //不过看起来,可有可无,删掉照样通过

template<class T> class array {
	int size;
public:
	array();
	//请注意,因为编译器将以下一行代码作为普通函数(array 类的 friend)的声明进行读取,
	//所以编译期间不会出现错误消息。但是链接期间会出问题哦 error LNK2019: unresolved external symbol
	//friend std::ostream& operator<< (std::ostream&, const array<T>&);
	//但是,由于operator<<有一个模板形参类型array<T>,因此在声明函数之前,必须声明array<T>。
	friend ostream& operator<< <T> (ostream&, const array<T>&);

};

template<class T> array<T>::array() {size = 1024;}

template<class T> ostream& operator<<(ostream& out, const array<T>& rhs)
{return out << '[' << rhs.size << ']';}

int main()
{
	cout
		<< "creating an array of int... " << flush;
	array<int> foo;
	cout << "done/n";
	cout << foo << endl;
	return 0;
}

 

 

转自:http://blog.csdn.net/lychee007/article/details/4428161

posted @ 2011-12-17 13:35  MagiCube  阅读(516)  评论(0编辑  收藏  举报