C++ 模板的部分特化和完全特化(已翻译)

 2024-03-02 04:04:22  阅读 0

模板函数模板的声明方式相同。 模板参数列表在类定义/模板定义之前声明。 例如:

// 类模板
template <class T1, class T2>
class A{
    T1 data1;
    T2 data2;
};
// 函数模板
template <class T>
T max(const T lhs, const T rhs){   
    return lhs > rhs ? lhs : rhs;
}

完全专业化

通过完全专业化模板,您可以针对一组特定参数自定义当前模板。 类模板和函数模板都可以完全专业化。 完全专用的模板参数列表应该为空,并且应该给出“模板参数”列表:

// 全特化类模板
template <>
class A<int, double>{
    int data1;
    double data2;
};
// 函数模板
template <>
int max(const int lhs, const int rhs){   
    return lhs > rhs ? lhs : rhs;
}

请注意,类模板的完全特化在类名后给出“模板参数”,但函数模板在函数名后不给出“模板参数”。 这是因为编译器可以从 int max(const int, const int) 的函数签名推断出它是 T max(const T, const T) 的特化。

专门歧义

上面的函数模板不需要指定“模板参数”,因为编译器可以通过函数签名来推断它,但有时这个过程是不明确的:

template <class T>
void f(){ T d; }
template <>
void f(){ int d; }

此时编译器并不知道f()是从f()特化而来的,编译时会报错:

error: no function template matches function template specialization 'f'

这时候我们需要显式指定“模板参数”:

template <class T>
void f(){ T d; }
template <>
void f<int>(){ int d; }

部分专业化

与完全特化类似,部分特化也用于为参数集定制模板,但部分特化模板需要进一步实例化以形成明确的签名。 值得注意的是,函数模板不允许部分特化,这在 C++: Item 25 中有更详细的讨论。此后也声明了部分特化,剩余的“模板形参”和必要的“模板实参”需要给予。 例如:

template <class T2>
class A<int, T2>{
    ...
};

函数模板不允许部分专业化。 以下声明将导致编译错误:

template <class T1, class T2>
void f(){}
template <class T2>
void f<int, T2>(){}

但函数是允许重载的,并且声明另一个函数模板可以取代部分特化的需要:

template <class T2>
void f(){}              // 注意:这里没有"模板实参"

大多数情况下,函数模板重载可以满足部分函数特化的需要。 std 命名空间是一个例外。 std是一个特殊的命名空间,用户可以在其中专门化模板,但不允许添加模板(事实上,添加任何内容都是被禁止的)。 因此不允许向 std 添加重载函数,更详细的情况在 C++: Item 25 中给出。

标签: 模板 函数 声明

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码