我想在一个地方知道这三个概念的精确而简洁的定义。答案的质量应该取决于以下两点。
- 展示一个简单的代码片段来展示概念/技术的用途和用途。
- 要简单易懂,以便没有任何接触过该领域的程序员可以掌握它。
笔记:
可能有很多正确的答案,因为每个概念都有许多不同的方面。如果有很多好的答案,我最终会将问题变成 CW 并汇总答案。
-- 接受后编辑 --
Boost 有一篇关于泛型编程概念的好文章
我想在一个地方知道这三个概念的精确而简洁的定义。答案的质量应该取决于以下两点。
笔记:
可能有很多正确的答案,因为每个概念都有许多不同的方面。如果有很多好的答案,我最终会将问题变成 CW 并汇总答案。
-- 接受后编辑 --
Boost 有一篇关于泛型编程概念的好文章
概念是对类型的一组要求。例如,您可以有一个名为“RandomAccessible”的概念,它将要求置于它operator[](int)
在 O(1) 时间内实现的类型上。
由于概念已从即将到来的 C++ 标准中删除,它们仅作为文档无形地存在于 C++ 中。例如,您可以阅读SGI 对 Container 概念的描述。
当一个类型满足一个概念的所有要求时,你就称它为该概念的模型。例如,std::vector
是 Container 概念的模型(或等价的std::vector
“模型”Container)。
最后,策略是一个行为单元,它可以与其他行为单元组合以构建复杂的类。例如,假设您想构建两个类:一个固定大小的数组和一个动态调整大小的数组。这两个类有很多共享的功能,但是它们的存储机制和它们的一些功能不同(例如你不能调用push_back
一个固定大小的数组)。
template <class T, class StoragePolicy>
class array : public StoragePolicy
{
public:
T& operator[](int i) { return data[i]; }
};
template <class T, int N>
class fixed_storage
{
T data[N];
};
template <class T>
class dynamic_storage
{
T* data;
public:
void push_back(const T& value)
{
// Code for dynamic array insertion
}
};
用法如下:
int main()
{
array<int, fixed_storage<int, 10> > fixed_array;
array<int, dynamic_storage<int> > dynamic_array;
dynamic_array.push_back(1);
fixed_array[9] = dynamic_array[0];
}
显然这是一个非常粗略和不完整的例子,但我希望它能够阐明政策背后的概念。
请注意,在示例中,我们可以说fixed_storage
和dynamic_storage
是StoragePolicy
概念的“模型”。当然,我们需要正式定义StoragePolicy
概念对其模型的要求。在这种情况下,它只是定义一个可索引的data
成员变量。
概念是类型必须满足的一组要求,以便对概念进行建模。
例如,类型T
是LessThanComparable
if 对于一对对象a
和b
类型T
,表达式a < b
是格式良好的,可转换为bool
并引发严格的弱排序关系。该类型int
是 的模型的示例LessThanComparable
。
概念可以形成细化层次结构。如果 的要求是 的要求的超集,则概念A
是概念的改进。例如,是对 的改进。B
A
B
BidirectionalIterator
ForwardIterator
概念用于限制模板可以专门化的类型集。例如,该std::sort
算法可以接受一对对象,只要它们对RandomAccessIterator
.
std::vector<int> vec;
std::list<int> list;
// OK, std::vector<int>::iterator is a model of `RandomAccessIterator`.
std::sort(vec.begin(), vec.end());
// error, std::list<int>::iterator is only a model of `BidirectionalIterator`.
std::sort(list.begin(), list.end());
请注意,概念是 C++ 标准和各种其他文档中使用的非正式对象。该语言不直接支持概念(尚未)。
Ao SGI 文档中提到的“模型”是指在 C++0x 提案中作为“概念”引入的内容:它的编译时等同于 OO 建模中的“接口”。它总结了对模板参数的通用代码提出的要求。
作为一个例子,你可以说函数的OutputIterator
参数std::transform
应该实现operator++()
并且operator=( T )
为了函数工作。
策略是另一回事:它使算法可以从外部改变。一个很好的例子是Allocator
stl 容器中使用较少的参数:它告诉算法如何分配内存。如果愿意,可以制作一个std::vector<int, AllocateOnCloud>
,其中所有vector
函数将在云中分配内存而不是在堆上。(请注意,我不倾向于实现这个分配器)。