2009-06-04 101 views
4

我们为您的字符串转换一个小工具功能,这样我就不必去围绕创建ostringstream对象遍布模板专业化其中模板类型也是一个模板

template<typename T> 
inline string ToString(const T& x) 
{ 
    std::ostringstream o; 
    if (!(o << x)) 
     throw BadConversion(string("ToString(") + typeid(x).name() + ")"); 
    return o.str(); 
} 

我想要的地方为没有默认超载运算符的字符串流(即std :: pair,std :: set,我自己的类)的实例提供了此方法的一些特殊功能,并且遇到了与模板有关的困难。我将与标准::对举个例子说明,如果我想能够

string str = ToString(make_pair(3, 4)); 

我能想到的这样做是定义明确的分工为INT

template<> 
inline string ToString(const pair<int,int>& x) 
{ 
    std::ostringstream o; 
    if (!(o << "[" << x.first << "," << x.second << "]")) 
     throw BadConversion(string("ToString(pair<int,int>)")); 
    return o.str(); 
} 

的唯一途径有没有一种方法可以为通用情况定义此方法?

template<> 
inline string ToString(const pair<T1,T2>& x) 
{ 
    std::ostringstream o; 
    if (!(o << "[" << x.first << "," << x.second << "]")) 
     throw BadConversion(string("ToString(pair<T1,T2>)")); 
    return o.str(); 
} 

回答

16

不专门化模板,但重载它。编译器会根据它们的函数参数类型的特殊性(这称为偏序)来确定要使用哪个函数模板。

template<typename T1, typename T2> 
inline string ToString(const std::pair<T1, T2>& x) { 
    std::ostringstream o; 
    if (!(o << "[" << x.first << "," << x.second << "]")) 
     throw BadConversion(string("ToString(pair<T1,T2>)")); 
    return o.str(); 
} 

一般来说,部分排序会导致您期望的结果。更具体地说,考虑有这两个功能

template<typename T> void f(T); 
template<typename T, typename U> void f(pair<T, U>); 

现在,看一个人是否是至少为一体的专业化的另外一个,我们测试了两个函数模板如下:

  1. 选择一些独特键入每个模板参数,将其替换为函数参数列表。
  2. 将该参数列表作为参数,在另一个模板上进行参数推导(使用那些参数对其他模板进行虚拟调用)。如果扣除成功并且不需要转换(加入const就是这样)。
  3. 用于上述

实施例:

  1. 取代一些类型X1T给我们一些类型,称之为X1。反对pair<T, U>的论点扣除X1将不起作用。所以第一个不像第二个模板那么专业化。
  2. 将类型Y1Y2代入pair<T, U>得到pair<Y1, Y2>。对T的第一个模板作品:T将推算为pair<Y1, Y2>。所以第二个至少和第一个一样专业化。

规则是,一个函数模板A比另一个B更专业化,如果A至少和B一样专业化,但是B至少不像A那么专业。所以,第二个在我们中获胜例如:它更专业化,如果我们原则上可以调用两个模板函数,它将被选中。

恐怕,这个概述很匆忙,我只做了类型参数,并跳过了一些细节。在C++标准规范中查看14.5.5.2以查看血淋淋的细节。摹

+0

感谢您的好解释 – 2009-06-04 00:42:43

+0

欢迎您:) – 2009-06-04 00:51:43

1

怎么样使用型性状类似这样的序列化不同类型的流:

template<typename T> 
struct Traits { 
    static inline bool ToStream(std::ostringstream& o, const T& x) { 
    return o << x; 
    } 
}; 

template<typename T1, typename T2> 
struct Traits<std::pair<T1, T2> > { 
    static inline bool ToStream(std::ostringstream& o, const std::pair<T1, T2>& x) { 
    return o << "[" << x.first << "," << x.second << "]"; 
    } 
}; 

template<typename T> 
inline std::string ToString(const T& x) 
{ 
    std::ostringstream o; 
    if (!Traits<T>::ToStream(o, x)) 
    return "Error"; 
    return o.str(); 
} 

注:“模板<>”从专业化部分是可选的,代码编译罚款没有它。 您可以在异常消息的特征中进一步添加方法。