转自http://blog.csdn.net/delphiwcdj/archive/2010/07/07/5719148.aspx

[1] 当编译器看到模板定义的时候,它不立即产生代码。 只有在看到用到模板时 ,如调用了函数模板或定义了类模板的对象的时候,编译器才产生特定类型的模板实例 。
[2] 一般而言,当调用函数的时候,编译器只需要看到函数的声明。类似地,定义类类型的对象时,类定义必须可用,但成员函数的定义不是必须存在的。因此,应该将类定义和函数声明放在头文件中,而普通函数和类成员函数的定义放在源文件中。 
[3] 模板则不同:要进行实例化,编译器必须能够访问定义模板的源代码。 当调用函数模板或类模板的成员函数的时候,编译器需要函数定义,需要哪些通常放在源文件中的代码。
[4] 标准C++为编译模板代码定义了两种模型。 所有编译器都支持第一种模型,称为“包含”模型( inclusion compilation model) ;只有一些编译器支持第二种模型,“分别编译”模型( separate compilation model) 。
[5] 在两种模型中,构造程序的方式很大程度上是相同的:类定义和函数声明放在头文件中,而函数定义和成员定义放在源文件中。两种模型的不同在于,编译器怎样使用来自源文件的定义 。
[6] 在包含编译模型,编译器必须看到用到的所有模板的定义。一般而言,可以通过在声明函数模板或类模板的头文件中添加一条#include指示使定义可用,该#include引入了包含相关定义的源文件 。
[7] 在分别编译模型中,编译器会为我们跟踪相关的模板定义。但是,我们必须让编译器知道要记住给定的模板定义,可以使用export关键字来做这件事 。export关键字能够指明给定的定义可能会需要在其他文件中产生实例化 。
[8] 在一个程序中,一个模板只能定义为导出一次。 一般我们在函数模板的定义中指明函数模板为导出的 ,这是通过在关键字template之前包含export关键字而实现的。对类模板使用export更复杂一些 ,记得应该在类的实现文件中使用export,否者如果在头文件中使用了export,则该头文件只能被程序中的一个源文件使用。
[9] 导出类的成员将自动声明为导出的。也可以将类模板的个别成员声明为导出的,在这种情况下,关键字export不在类模板本身指定,而是只在被导出的特定成员定义上指定。任意非导出成员的定义必须像在包含模型中一样对待:定义应放在定义类模板的头文件中。

[问题] 
确定你的编译器使用的是那种编译模型。编写并调用函数模板,在保存未知类型对象的vector中查找中间值。(注:中间值是这样一个值,一半元素比它大,一半元素比它小。)用常规方式构造你的程序:函数定义应放在一个文件中,它的声明放在一个头文件中,定义和使用函数模板的代码应包含该头文件。

在VS2008下测试,发现编译器可以使用包含编译模型,但是不支持分别编译模型 。

[代码] 
包含编译模型,在VS2008测试通过

  1. // --------- 
  2. // median.h 
  3. // --------- 
  4. // header guard  
  5. #ifndef MEDIAN_H 
  6. #define MEDIAN_H 
  7. #include <vector> 
  8. #include <algorithm> 
  9. using std::vector; 
  10. // if the vector has the middle value return true  
  11. // and save the value into the second parameter 
  12. template <typename T> 
  13. bool median(const vector<T>&, T&); 
  14. #include "median.cpp"// include the implementation  file 
  15. #endif 
  16. // --------- 
  17. // median.cpp 
  18. // --------- 
  19. template <typename T> 
  20. bool median(const vector<T>& c, T& m) 
  21.     // create the duplication  
  22.     vector<T> temp(c); 
  23.     if (temp.size()%2==0) 
  24.     { 
  25.         return false
  26.     } 
  27.     sort(temp.begin(), temp.end()); 
  28.     // check 
  29.     vector<T>::size_type index=temp.size()/2; 
  30.     if (temp[index]>temp[index-1] && temp[index]<temp[index+1]) 
  31.     { 
  32.         m=temp[index]; 
  33.         return true
  34.     }  
  35.     else 
  36.     { 
  37.         return false
  38.     } 
  39. // --------- 
  40. // main.cpp 
  41. // --------- 
  42. #include <iostream> 
  43. #include "median.h" 
  44. using std::cout; 
  45. using std::endl; 
  46. int main() 
  47.     int ia1[]={1, 2, 3, 4, 5, 6, 7}; 
  48.     int ia2[]={1, 2, 3, 4}; 
  49.     int ia3[]={1, 2, 3, 3, 4, 5, 6}; 
  50.     vector<int> ivec1(ia1, ia1+7); 
  51.     vector<int> ivec2(ia2, ia2+4); 
  52.     vector<int> ivec3(ia3, ia3+7); 
  53.     int m; 
  54.     if (median(ivec1,m)) 
  55.     { 
  56.         cout<<"median: "<<m<<endl; 
  57.     } 
  58.     else 
  59.     { 
  60.         cout<<"no median"<<endl; 
  61.     } 
  62.     if (median(ivec2,m)) 
  63.     { 
  64.         cout<<"median: "<<m<<endl; 
  65.     } 
  66.     else 
  67.     { 
  68.         cout<<"no median"<<endl; 
  69.     } 
  70.     if (median(ivec3,m)) 
  71.     { 
  72.         cout<<"median: "<<m<<endl; 
  73.     } 
  74.     else 
  75.     { 
  76.         cout<<"no median"<<endl; 
  77.     } 
  78.     return 0;