泛型编程:Boost中的泛型编程技术



介绍
Generic programming is about generalizing software components so that they can be easily reused in a wide variety of situations. In C, and function templates are particularly effective mechanisms for generic programming because they make the generalization possible without sacricing efficiency.

泛型编程是有关般化(generalizing)软件Software组件使得他们那可以在广泛情况下得到重用编程技术在C类和模板对泛型编程是尤其有效率机制他们在无需牺牲效率情况下实现这种般化(generalizing)

As a simple example of generic programming, we will look at how _disibledevent=>const char* last = ((const char*)region2) + n;
char* result = (char*)region1;
while (first != last)
*result = *first;
result;
}

The memcpy function is already generalized to some extent by the use of void* so that the function can be used to copy .gif' />s of dferent kinds of data. But what the data we would like to copy is not in an .gif' />? Perhaps it is in a linked list. Can we generalize the notion of copy to any sequence of elements? Looking at the body of memcpy, the function's minimal requirements are that it needs to to traverse through the sequence using some sort of poer, access elements poed to, write the elements to the destination, and compare poers to know when to stop. The C standard library groups requirements such as these o concepts, in this the Input Iterator concept (for region2) and the Output Iterator concept (for region1).

memcpy已经在某种程度上通过void*使用实现了般化可以用来拷贝任何类型数据但是如果我们想要拷贝数据不在中呢?可能它在个链表中我们可以般化拷贝任何元素序列这个概念吗?看看memcpy所需要最低要求是使用某种指针遍历序列存取指向元素并比较指针来得知何时停止C标准库把类似这样需求归类为概念在这例中是Input Iterator概念Output Iterator概念

If we rewrite the memcpy as a function template, and use the Input Iterator and Output Iterator concepts to describe the requirements _disibledevent=>*result = *first;
result;
}

Using the generic copy function, we can now copy elements from any kind of sequence, including a linked list that exports iterators such as std::list.

使用泛型copy我们现在可以拷贝来自任何种类序列元素包括提供了iterators链表像std::list



# <list>
# <vector>
# <iostream>

{
const N = 3;
std::vector<> region1(N);
std::list<> region2;
region2.push_back(1);
region2.push_back(0);
region2.push_back(3);

std::copy(region2.begin, region2.end, region1.begin);
for ( i = 0; i < N; i)
std::cout << region1[i] << " ";
std::cout << std::endl;
}


--------------------------------------------------------------------------------

Anatomy of a Concept
概念剖析
A concept is a requirements, where the requirements consist of valid expressions, associated types, invariants, and complexity guarantees. A type that satisfies the of requirements is said to model the concept. A concept can extend the requirements of another concept, which is called refinement.

个概念是数个要求(requirements)集合其中要求包括有效表达式相关类型不变量和复杂度保证个满足这样套要求类型被称为模塑这个概念个概念可以扩展另外个概念要求这个称为refinement

Valid Expressions are C expressions which must compile successfully for the objects involved in the expression to be considered models of the concept.
有效表达式是必须成功编译C表达式对于表达式中包括对象称为概念模型
Associated Types are types that are related to the modeling type in that they participate in _disibledevent=>


Invariants are run-time characteristics of the objects that must always be true, that is, the functions involving the objects must preserve these characteristics. The invariants often take the form of pre-conditions and post-conditions.
不变量是对象运行时性质必须永远为真也就是说对象中必须保有这些性质不变量经常以pre-condition和post-condition形式出现
Complexity Guarantees are maximum limits _disibledevent=>
个经常和traits类并用技术是tag dispatching它是种使用重载来分派基于同属性区别类型这项技术个很好哦实现是C标准库中std::advance它使个迭代器步进n次根据迭代器种类可以对迭代器施以区别优化如果迭代器是random access(可以向前和向后跳跃任意距离)那么advance可以简单用in来实现而且是非常有效率:常量时间其他迭代器必须分n步前进使得操作表现为线性如果迭代器是bidirectional那么它使得n可以为负数因此我们必须决定是否使迭代器步进或者步退

The relation between tag dispatching and traits es is that the property used for dispatching (in this the iterator_category) is often accessed through a traits . The advance function uses the iterator_traits to get the iterator_category. It then makes a call the the overloaded advance_dispatch function. The appropriate advance_dispatch is selected by the compiler based _disibledevent=>


tag dispatching和traits类的间关系是用来分派属性(在此例中是iterator_category)经常由个traits类来取得advance使用iterator_traits类来获得iterator_category然后它个重载了advance_dispatch由编译器根据iterator_category解析(resolve)为类型来决定具体重载版本iterator_category要么是input_iterator_tag要么是bidirectional_iterator_tag要么是random_access_iterator_tagtag是个仅仅用来传达tag dispatching或者类似技术中用到些属性参考这个页面来获得有关iterator tags更具体描述

std {
struct input_iterator_tag { };
struct bidirectional_iterator_tag { };
struct random_access_iterator_tag { };
detail {
template < InputIterator, Distance>
void advance_dispatch(InputIterator& i, Distance n, input_iterator_tag) {
while (n--) i;
}
template < BidirectionalIterator, Distance>
void advance_dispatch(BidirectionalIterator& i, Distance n,
bidirectional_iterator_tag) {
(n >= 0)
while (n--) i;

while (n) --i;
}
template < RandomAccessIterator, Distance>
void advance_dispatch(RandomAccessIterator& i, Distance n,
random_access_iterator_tag) {
i n;
}
}
template < InputIterator, Distance>
void advance(InputIterator& i, Distance n) {
typename iterator_traits<InputIterator>::iterator_category category;
detail::advance_dispatch(i, n, category);
}
}


--------------------------------------------------------------------------------

Adaptors
配接器
An adaptor is a template which builds _disibledevent=> Reference = complicated default,
Poer = complicated default,
Category = complicated default,
Distance = complicated default
>
struct filter_iterator_generator {
typedef iterator_adaptor<
Iterator,filter_iterator_policies<Predicate,Iterator>,
Value,Reference,Poer,Category,Distance> type;
};

Now, that's complicated, but producing an adapted filter iterator is much easier. You can usually just write:

现在虽然generator本身是复杂但是创建个配接了filter iterator更加容易了你通常可以仅仅这么写:

boost::filter_iterator_generator<my_predicate,my_base_iterator>::type


--------------------------------------------------------------------------------

Object Generators
An object generator is a function template whose _disibledevent=>



For example, given:

例如给出:

struct widget {
void tweak();
};
std::vector<widget *> widget_ptrs;

By chaining two standard object generators, std::bind2nd and std::mem_fun, we can easily tweak all widgets:
通过把两个标准object generatorstd::bind2nd和std::mem_fun链在我们可以轻易地拧上所有widgets:

void tweak_all_widgets1( arg)
{
for_each(widget_ptrs.begin, widget_ptrs.end,
bind2nd(std::mem_fun(&widget::tweak), arg));
}

Without using object generators the example above would look like this:

不使用object generator上面例子可能看上去是这样:

void tweak_all_widgets2( arg)
{
for_each(struct_ptrs.begin, struct_ptrs.end,
std::binder2nd<std::mem_fun1_t<void, widget, > >(
std::mem_fun1_t<void, widget, >(&widget::tweak), arg));
}

As expressions get more complicated the need to reduce the verbosity of type specication gets more compelling.

当表达式变得更加复杂减轻类型介绍说明冗长要求变得更加迫切


--------------------------------------------------------------------------------

Policy Classes
A policy is a template parameter used to transmit behavior. An example from the standard library is std::allocator, which supplies memory management behaviors to standard containers.

个policy类时个用来传播行为模板参数来自标准库个例子是std::allocator它给标准容器提供内存管理行为

Policy es have been explored in detail by Andrei Alexandrescu in this paper. He writes:

policy类在Andrei Alexandrescu这篇文章中被深度探究他写道:

Policy es are implementations of punctual design choices. They are inherited from, or contained within, other es. They provide dferent strategies under the same syntactic erface. A using policies is templated having one template parameter for each policy it uses. This allows the user to select the policies needed.

policy类是严格设计个是实现他们从其他类继承或者包含于其他类他们在同样句法接口基础上提供区别策略个使用策略类为每个它使用策略提供个模板参数这使得用户选择他们需要策略

The power of policy es comes from their ability to combine freely. By combining several policy es in a template with multiple parameters, one achieves combinatorial behaviors with a linear amount of code.

policy类威力来自于他们自由组合能力通过在个模板类中用多个参合好几个policy类实现了在线性数量代码中提供组合行为

Andrei's description of policy es describe their power as being derived from their granularity and orthogonality. Boost has probably diluted the distinction in the Iterator Adaptors library, where we transmit all of an adapted iterator's behavior in a single policy . There is precedent for this, however: std::char_traits, despite its name, acts as a policies that determines the behaviors of std::basic_.

Andrei对于policy类描述介绍说明他们威力来自于他们颗粒性和正交性Boost可能已经冲淡了在Iterator Adaptor库中区别我们在个policy类中传播所有adapted iterator行为然而这有个先例:std::char_traits不管它名字就像个policy 样行为决定std::basic_行为

Tags:  泛型技术 java泛型编程 泛型编程与stl 泛型编程

延伸阅读

最新评论

发表评论