C++ Templates (2.3 类模板的局部使用 Partial Usage of Class Templates)

微信扫一扫,分享到朋友圈

C++ Templates (2.3 类模板的局部使用 Partial Usage of Class Templates)

返回完整目录

目录

  • 2.3 类模板的局部使用 Partial Usage of Class Templates

2.3 类模板的局部使用 Partial Usage of Class Templates

类模板通常在它实例化的模板实参上进行多种操作(包括构造和析构),这给人一种印象:模板实参必须提供所有类模板的所有成员函数的所有操作。但是事实并非如此:模板实参仅需提供必要的操作而非可能需要的操作。

比如说,如果类 Stack<>
提供一个成员函数 printOn()
用于打印整个stack的内容,并对每个元素调用 operator<<

template <typename T>
class Stack
{
...
void printOn(std::ostream& strm) const
{
for(T const& elem: elems)
{
strm << elem << ' ';       //每个元素调用<<
}
}
}

但这依然可以使用没有定义 operator<<
的类作为该类模板的模板实参:

Stack<std::pair<int,int>> ps;      //注意: std::pair<>没有定义operator<<
ps.push({4, 5});      //OK
ps.push({6,7});      //OK
std::cout << ps.top().first << '\n'; //OK
std::cout << ps.top().second << '\n';      //OK

只有当调用这样的stack的 printOn()
方法时,该代码才会生成错误,因为它不能实例化对该特殊类型的 operator<<
的调用:

ps.printOn(std::cout);      //ERROR: 元素类型不支持operator<<

2.3.1 Concepts

这引发了一个问题,如何知道哪些是模板实例化所需要的操作?术语 概念(Concept)
用于指示约束条件的集合,并在模板库中重复使用。比如,C++标准库依赖于 随机访问迭代器(random access iterator)
默认构造(default constructible)

当前(C++17),concepts只能或多或少地在文档中进行表述(比如代码注释)。这可能是个重要的问题,因为未遵循约束条件的错误可能引起恶心的错误消息(详见第9.4节)。

许多年来,有许多方法和试验来支持concepts的定义和验证,将其作为语言特性。然而,截止C++17还没有标准化的方法。

自从C++11以后,至少可以通过使用 static_assert
关键字和预定义的类型特性来检查基本的约束条件,比如:

template <typename T>
class C
{
static_assert(std::is_default_constructible<T>::value, "Class C requires default-constructible elements");
...
}

没有该断言,如果需要默认构造函数,编译依然会失败。然而,该错误信息可能包含整个模板实例化的历史,从开始实例化到真实的模板定义(即错误检测到的地方,详见9.4节)。

然而,更多复杂的代码需要检查,比如,类型T的对象提供一种特殊的成员函数或者他们可以使用操作 <
进行比较。详见19.6.3节的一个详细的代码例程。

参考附件E关于更多的有关C++ Concept的讨论。

微信扫一扫,分享到朋友圈

C++ Templates (2.3 类模板的局部使用 Partial Usage of Class Templates)

vscode 调试 node.js

上一篇

首款搭载Apple Silicon的Mac将于 11 月发布

下一篇

你也可能喜欢

C++ Templates (2.3 类模板的局部使用 Partial Usage of Class Templates)

长按储存图像,分享给朋友