模板特化,其中模板化类型也是模板

Jam*_*ook 5 c++ templates

我已经为字符串转换创建了一个小的实用程序函数,这样我就不必在整个地方创建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();
}
Run Code Online (Sandbox Code Playgroud)

我想为没有默认重载<< string for stringstream的实例(即std :: pair,std :: set,我自己的类)的实例提供此方法的一些特殊化,并且我遇到了模板的困难.我将用std :: pair示例说明,如果我想能够

string str = ToString(make_pair(3, 4));
Run Code Online (Sandbox Code Playgroud)

我能想到的唯一方法是为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();
}
Run Code Online (Sandbox Code Playgroud)

有没有办法可以为通用案例定义这个?

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();
}   
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 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();
}
Run Code Online (Sandbox Code Playgroud)

通常,部分排序将产生您期望的结果.更详细地说,考虑具有这两个功能

template<typename T> void f(T);
template<typename T, typename U> void f(pair<T, U>);
Run Code Online (Sandbox Code Playgroud)

现在,为了看一个是否至少与另一个一样专业,我们测试两个函数模板的以下内容:

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

以上示例:

  1. 代某种类型的X1进入T给了我们某种类型的,把它X1.X1反对的论证推论是 pair<T, U>行不通的.所以第一个并不像第二个模板那样专业.
  2. 代类型Y1Y2pair<T, U>的产率pair<Y1, Y2>.对T第一个模板进行参数推导工作:T将推断为pair<Y1, Y2>.所以第二个至少和第一个一样专业.

规则是,函数模板A比其他B更专业,如果A至少与B一样专用,但B至少不如A专用.所以,第二个在我们的例子中获胜:它更专业,如果我们原则上可以调用两个模板函数,那么它将被选择.

我担心,这个概述很匆忙,我只是为类型参数做了这个并跳过了一些细节.查看14.5.5.2C++标准规范以查看血淋淋的细节.G