2013-10-03 36 views
0

我认为,一个函数模板参数由类标识符只是声明,例如:基本类型的函数模板参数

template<class T1, class T2> void fun(T1 a, T2 b){} 

但是我发现其中基本类型,可以作为一个参数另一个例子:

template<int R, int C> 
void fun(double (&arr)[R][C]) 
{ 
    for(int i = 0; i < R; ++i) 
    { 
      for(int j = 0; j < C; ++j) 
      { 
       cout<<arr[i][j]<<" "; 
      } 
      cout<<endl; 
    } 
} 

函数执行如下:

fun(myArray); 

如何该机制有效吗?你能否给我另外一个基本类型可以用作函数模板参数的例子?

+3

'std :: array '。 – juanchopanza

+1

或[元组获取](http://en.cppreference.com/w/cpp/utility/tuple/get)。 – Danstahr

+3

Google *非类型模板参数* – Praetorian

回答

2

在我的旅行,我已经找到了模板参数为基本类型三个主要用途:

之一就是建立一个函数模板,需要一个C数组。这就是你在这里张贴的东西,但更常见的我看到这适用于char阵列,具有:

template <size_t N, typename Char> 
string MakeString (Char const (&chars)[N]) 
{ 
    return string (chars, N); 
} 

int main() 
{ 
    string hi = MakeString ("Hello"); 
    cout << hi; 
} 

另一个用途是建立一种使用模板元编程便宜的属性系统。例如,假设您有一堆旨在用某些有线协议表示消息的类,并且出于测试目的,您希望将消息类的实际大小与规范所说的大小应该是的大小进行比较。

enum MsgType 
{ 
    MsgType_Foo, 
    MsgType_Bar 
}; 

class FooMsg 
{ 
    uint32_t mField; 
    char mName [9]; 
}; 

class BarMsg 
{ 
    char mPrice [8]; 
    static const size_t SpecSize = 8; 
}; 

template <MsgType MT> size_t SpecSize(); 

template <> size_t SpecSize <MsgType_Foo>() 
{ 
    return 13; 
} 

template <> size_t SpecSize <MsgType_Bar>() 
{ 
    return 9; 
} 

int main() 
{ 
    assert (SpecSize <MsgType_Foo>() == sizeof (FooMsg)); 
    assert (SpecSize <MsgType_Bar>() == sizeof (BarMsg)); 
} 

请注意,如果你运行这个程序,除非你做平台特有的东西(比如#pragma pack (push, 1))厘定包装断言将失败。这是测试打算抓住的事情之一!

最后,另一种常见用法更具体,但该技术可应用于您自己的代码。在Boost.Tuple和现在的C++ 11中,tuple类使用模板函数get<size_t>作为访问元素的手段。下面是从en.cppreference.com采取了一个例子:

#include <iostream> 
#include <string> 
#include <tuple> 

int main() 
{ 
    auto t = std::make_tuple(1, "Foo", 3.14); 
    // index-based access 
    std::cout << "(" << std::get<0>(t) << ", " << std::get<1>(t) 
       << ", " << std::get<2>(t) << ")\n"; 
} 

我想你可以认为这是两个前面的例子中的一个特例。这是更多的模板元编程技巧,结果在某些情况下非常有用。例如,

1

好像你可能是由模板经常看起来像下面的事实相混淆:

template <class T> void Bar(T param); 

有在这方面是更具描述性的synonym:类型名称。这告诉你任何typename都可以用作模板参数,包括从模板生成的基本类型或类型。因此,而不是写上面,你可以写:

template <typename T> void Bar(T param); 

除了类型,您可以通过类型some实例模板,你证明。这通常用于在类模板中设置数组大小,但有许多其他用途。正如Praetorian在评论中提到的,您可以通过搜索non-type template arguments找到更多信息。

1

尽管他们的语法允许 class模板参数,如:template <class T>,从来没有任何意图,他们被限制在用户定义的类型。

换句话说,你可以总是传递一个基本类型作为模板参数除非用户已经做了一些代码在模板中,以防止它,如与模板内static_assert或代码,调用传递类型的成员函数。

对于非类型的模板参数,您可以指定基本上任何类型。该模板可以使用该类型的值进行实例化,也可以转换为该类型。


1.您可以使用typename如果你喜欢 - 有些人喜欢,因为它传达的是任何类型的名称是允许的思想工作做得更好。

相关问题