13-15 别名模板
在第10.7节——类型别名与类型别名中,我们讨论了如何通过类型别名为现有类型定义别名。
为所有模板参数均显式指定的类模板创建类型别名type alias时,其操作方式与普通类型别名完全相同:
#include <iostream>
template <typename T>
struct Pair
{
T first{};
T second{};
};
template <typename T>
void print(const Pair<T>& p)
{
std::cout << p.first << ' ' << p.second << '\n';
}
int main()
{
using Point = Pair<int>; // create normal type alias
Point p { 1, 2 }; // compiler replaces this with Pair<int>
print(p);
return 0;
}
此类别名可在局部(例如函数内部)或全局范围内定义。
别名模板
在其他情况下,我们可能需要为模板类定义类型别名,但别名中并非所有模板参数都已定义(这些参数将由类型别名的使用者提供)。为此,我们可以定义别名模板alias template,——这是一种可用于实例化类型别名的模板。正如类型别名本身并不定义独立类型,别名模板同样不定义独立类型。
以下示例展示其工作原理:
#include <iostream>
template <typename T>
struct Pair
{
T first{};
T second{};
};
// Here's our alias template
// Alias templates must be defined in global scope
template <typename T>
using Coord = Pair<T>; // Coord is an alias for Pair<T>
// Our print function template needs to know that Coord's template parameter T is a type template parameter
template <typename T>
void print(const Coord<T>& c)
{
std::cout << c.first << ' ' << c.second << '\n';
}
int main()
{
Coord<int> p1 { 1, 2 }; // Pre C++-20: We must explicitly specify all type template argument
Coord p2 { 1, 2 }; // In C++20, we can use alias template deduction to deduce the template arguments in cases where CTAD works
std::cout << p1.first << ' ' << p1.second << '\n';
print(p2);
return 0;
}

在此示例中,我们定义了一个名为 Coord 的别名模板,作为 Pair
此示例有几点值得注意:
首先,与普通类型别名(可在代码块内定义)不同,别名模板必须在全局作用域中定义(所有模板皆如此)。
其次,在C++20之前,使用别名模板实例化对象时必须显式指定模板参数template arguments 。自C++20起,我们可使用别名模板推导机制alias template deduction——当别名类型支持CTAD时,该机制能从初始化表达式推导模板参数类型。
第三,由于CTAD不适用于函数参数function parameters,当别名模板作为函数参数时,必须显式定义其模板参数。换言之,我们这样做:
template <typename T>
void print(const Coord<T>& c)
{
std::cout << c.first << ' ' << c.second << '\n';
}
不是这样:
void print(const Coord& c) // won't work, missing template arguments
{
std::cout << c.first << ' ' << c.second << '\n';
}
这与我们使用 Pair 或 Pair

浙公网安备 33010602011771号