类实例能做做模板参数吗?

类实例能做做模板参数吗?

相信很多人都见过这种代码

1  template  < class  T >
2  class  Test
3  {
4  };
5 
6  int  main()
7  {
8      Test < int >  t;
9  }

这是类模板和模板类的最常见的使用了,但是想想看,见过这种写法吗?

1 // 

3 MyClass< std::string()> t;


注意红色的部分,我没有写错,它的确可以编译通过。这时候一串大大的疑问产生了:怎么类的实例也可以做模板参数吗?不是只有类型才能做模板参数么?难道。。。

我一开始看到这个的时候,也想不明白,怎么会呢?难道是幻觉?我决定测试一下,于是我写了下面一段代码:
 1 template <class T>
 2 struct return_value
 3 {
 4     typedef T type;
 5 };
 6 
 7 int main()
 8 {
 9     test< std::string()>::type t;
10 }

编译通过了,可以知道t的类型是:std::basic_string<char,std::char_traits<char>,std::allocator<char>> (void)
很长一串,写简单点就是 std::string (void).
这是个什么东西呢?如果是函数指针,怎么说也要有个*呀,可是没有。那这是什么呢?

它是个函数类型,不是函数指针,函数指针是指向函数类型的指针,所以没有*(感谢eXile)。

我给个例子吧,相信大家对boost::function不陌生吧,看下面的代码:

 1 std::string Test()
 2 {
 3     return "Hello World!";
 4 }
 5 
 6 boost::function< std::string()> func(Test);
 7 
 8 int main()
 9 {
10     std::cout<<func();
11 }

Hello World应该很熟悉了吧,而那个红色的模板参数呢,其实不是调用std::string的构造函数,而是传入std::string (void)(函数类型)。这个类型呢,没啥用,不能实例化,也不能调用(不是函数指针),它只是作为一种类型的签名而已。主要任务是告诉boost::function这个类,它将要接受的函数是一个接受void为参数,返回std::string的一个函数而已,用来做类型推导。

再看个例子吧,

 1  std:: string  Test(std:: string  str)
 2  {
 3       return   " Hello  "   +  str;
 4  };
 5 
 6  boost::function < std:: string  (std:: string ) >
 7      func(Test);
 8 
 9  int  main()
10  {
11      std::cout << func( " World " );
12  }

当把签名改成 std:: string  (std:: string )时,就容易理解了。这个看似和函数声明一样的模板参数,主要是为了让boost::function做类型推导。顺便加个括号,看起来像函数。括号里面是参数的类型,括号外面是返回类型。

这才是以函数指针作为模板类型的代码:
 1  std:: string  Test(std:: string  str)
 2  {
 3       return   " Hello  "   +  str;
 4  }
 5 
 6  template  < class  T >
 7  class  Type
 8  {
 9      typedef T type;
10  };
11 
12  int  main()
13  {
14       //  use function pointor as a template argument, it's OK.
15      Type < std:: string  ( * )(std:: string ) > ::type func  =  Test;
16       //  use the signature as a template argument, complier will tell you it's wrong.
17      Type < std:: string  (std:: string ) > ::type fun  =  Test;
18 
19  }

最后总结一下,这种类型的模板参数只是作为签名而存在,纯粹是为了做类型推导。不能实例化,不是函数指针,名字叫:函数类型。

你可能感兴趣的:(类实例能做做模板参数吗?)