`
feipigwang
  • 浏览: 792645 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

STL中的Concept和Boost库的Concept_Check

阅读更多

在Generic Programming当中,一个重要的概念就是Concept(滑稽的是,如果把这个Concept也翻译成“概念”,那就狗屁不通了。我倾向于说它是“操作集”)。Concept就是一组操作,如果一个type具有这些操作,那么就说这个type是这个Concept的一个model。
这其中的思想有那么一丁点像是OO当中的interface,一个class如果实现了一个interface,那么它就可以被当作这个interface来用。同样,如果一个type是一个Concept的model,那么所有接受这个Concept的操作也就可以接受这个type。

例如,在STL中,stable_sort这个算法必须接受RandomAccessIterator,这里RandomAccessIterator就是一个Concept,它规定自己的model必须可以进行下标运算,那么不满足这个Concept的type就无法被编译器接受(搞笑的是我在VC71里面把list<int> 的iterator传给stable_sort,它居然欣然接受,要知道list的iterator应该只是一个BidirectionalIterator 啊,比RandomAccessIterator弱多了。不过仔细看看代码,发现VC71的stable_sort接受BidirectionalIterator就够了,不知道是好还是坏)。在gcc下面如果传递一个BidirectionalIterator给stable_sort,会得到一堆不知所云的错误提示,让人摸不着头脑。

C++语言本身并没有对于Concept的直接支持,STL解决这个问题的办法是用了一些traits来限制iterator的特性,以达到在编译时期检查Concept的目的。但是traits导致的编译错误提示实在是太可怕了,我非常怀疑有哪个正常人可以从这些错误提示推测出自己错在哪里。

在boost库里面,提供了一个ConceptCheck库,它可以帮助我们写出带有Concept检查的代码,而且没有运行时的开销,一旦用户违反Concept限制,输出的错误提示也比较好懂。举个例子先,如果STL里面有ConceptCheck,那么它的stable_sort大约会这样:

#include <boost/concept_check.hpp>

template <class RandomAccessIter>
void stable_sort(RandomAccessIter first, RandomAccessIter last)
{
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
//... bla bla bla......
}

有了这个 function_requires ,如果再传递给它list的iterator,编译器(VC71)就会报这样的错:


c:\boost_1_31_0\boost\concept_check.hpp(642): error C2676: 二进制“+=” : “std::list<_Ty>::iterator”不定义该运算符或到预定义运算符可接收的类型的转换
with
[
_Ty=int
]

当然还有很多别的,但是至少它说了一点:传入的iterator不满足某个运算。这对于用户来说,应当是一个很有用的提示。
使用Concept Check还有一个额外的好处,那就是调用一个 function_requires可远比写一些traits容易,而且代码也清晰好维护。

这个好用的 function_requires 就定义在concept_check.hpp当中:
template <class Concept>
inline void function_requires(mpl::identity<Concept>* = 0)
{
#if !defined(NDEBUG)
void (Concept::*x)() = BOOST_FPTR Concept::constraints;
ignore_unused_variable_warning(x);
#endif
}

换句话说,function_requires只在Debug中起作用,那么是不是在Debug当中它就添加了overhead呢?其实也没有,仔细看看代码:
void (Concept::*x)() = BOOST_FPTR Concept::constraints;
这一句取constraints的地址。妙就妙在它让编译器“注意到”constraints,但又没有真正调用constraints,而constraints是一个虚函数,做实际的check。例如在RandomAccessIteratorConcept(检查iterator是否符合RandomAccessIterator的Concept)当中,constraint是这个样子:

template <class TT>
struct RandomAccessIteratorConcept
{
void constraints() {
function_requires< BidirectionalIteratorConcept<TT> >();
function_requires< ComparableConcept<TT> >();
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
typedef typename std::iterator_traits<TT>::iterator_category C;
function_requires< ConvertibleConcept< C,
std::random_access_iterator_tag> >();
typedef typename std::iterator_traits<TT>::reference R;
#endif

i += n; // require assignment addition operator
i = i + n; i = n + i; // require addition with difference type
i -= n; // require assignment subtraction operator
i = i - n; // require subtraction with difference type
n = i - j; // require difference operator
(void)i[n]; // require element access operator
}
TT a, b;
TT i, j;
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
typename std::iterator_traits<TT>::difference_type n;
#else
std::ptrdiff_t n;
#endif
};

从这个实现中我们完全可以读出RandomAccessIterator的具体含义:
1. 它必须是一个BidirectionalIterator
2. 它必须满足“可比较 (Comparable)”的Concept
3. 它还必须满足“可转换 (Convertible)”的Concept,而且是转换成自己的iterator_category类别
4. 它必须定义了reference这个type
5. 这是最重要的,它必须有difference_type,而且可以进行 +, -, +=, -= 的运算
还要记得,由于这个函数没有真正的被调用过,所以无论你怎么写,它都不会变成实际的代码,所以也不会影响运行效率的!

boost库除了提供了一系列的Concept Check以外,也鼓励我们自己写Concept Check,至于写法,从这个RandomAccessIteratorConcept的写法,大家也可以看出些端倪了:很简单的。

分享到:
评论

相关推荐

    C++准标准库Boost介绍

    4. **泛型编程和模板元编程**:Call_traits、Concept_check、Enable_if、In_place_factory、Mpl、Property_map、Static_assert、Type_traits等库,帮助开发者编写更加灵活和高效的模板代码。 5. **数学和数值计算**...

    C++各大有名库的介绍.docx

    如正则表达式(Boost.Regex)、解析器框架(Boost.Spirit)、图库(Boost.Graph)、Lambda函数对象(Boost.Lambda)、概念检查(Boost.Concept_Check)、元编程框架(Boost.MPL)以及多线程库(Boost.Thread)等。...

    C++著名程序库的比较和学习经验

    还有概念检查库concept check,元编程库Mpl,多线程库Thread,Python接口库,内存池管理库Pool,以及智能指针库smart_ptr等。Boost库的实用性和高质量使其成为现代C++开发者的必备工具,尽管有些库可能还在试验阶段...

    C++各大有名库的介绍.pdf

    著名的Boost库包括Regex、Spirit、Graph、Lambda、concept check、Mpl、Thread、Python、Pool、smart_ptr等。 GUI库 GUI库是指那些提供图形用户界面功能的库。著名的GUI库包括MFC、QT、WxWindows、Fox、WTL、GTK等...

    C++ 重要库

    - Concept Check:检查泛型编程中的概念一致性。 - Mpl:元编程框架,利用模板进行编译时计算。 - Thread:跨平台的多线程库。 - Python:允许将C++代码与Python互操作。 - Pool:内存池管理,优化内存分配。 ...

    常用C++第三方库.pdf

    它包含了许多实用的库,如Regex(正则表达式),Spirit(LL解析框架),Graph(图组件和算法),Lambda(函数对象定义),Concept Check(概念检查),MPL(元编程框架),Thread(多线程库),Python绑定,Pool内存...

    C++类库介绍.pdf

    Boost库包含了许多实用且先进的技术,如Regex库提供了正则表达式支持,Spirit是用于解析表达式的库,Graph库提供了图形组件和算法,Lambda允许在调用点定义匿名函数对象,还有用于概念检查的concept_check库,元编程...

    C++库介绍.pdf

    2. **C++准标准库 Boost**:Boost是一个强大的库集合,包含了许多潜在的C++标准候选,如正则表达式库(Regex)、Spirit LL解析框架、Graph图组件和算法、Lambda表达式、Concept Check、MPL元编程框架和Thread多线程库...

    C++标准库介绍.pdf

    Boost库提供了大量实用技术,其中一些已经成为了准标准,例如正则表达式库Regex、LL解析框架Spirit、图组件和算法Graph、函数式编程框架Lambda、泛型编程概念检查concept check、模板元编程框架Mpl以及可移植的C++多...

    C++ 各大名库,详细列举了目前C++使用的各大名库

    Boost包含了许多实用的库,如Regex(正则表达式)、Spirit(LL解析器框架)、Graph(图组件和算法)、Lambda(匿名函数对象)、Concept Check(泛型编程概念检查)、MPL(元编程框架)和Thread(多线程库)。Boost库...

    常用C++第三方库

    - **Concept Check**:用于验证泛型编程中的概念。 - **MPL**:元编程框架。 - **Thread**:跨平台多线程库。 - **Python**:支持 C++ 类与函数映射至 Python。 - **Pool**:内存池管理。 - **Smart_ptr**:五...

    C++各大有名库的介绍之C++标准库

    - **Concept Check**:用于验证泛型编程概念。 - **MPL**:元编程框架。 - **Thread**:便携式多线程库。 - **Python**:支持C++与Python之间的互操作。 - **Pool**:内存池管理。 - **Smart_ptr**:智能指针...

    C++库汇总

    - **Concept Check**:用于检查泛型编程中的概念。 - **MPL**:元编程框架。 - **Thread**:可移植的多线程库。 - **Python**:用于将 C++ 类和函数映射到 Python 中。 - **Pool**:内存池管理。 - **Smart_ptr**:...

    C++类库介绍 C++类库介绍

    Boost库是一个广受欢迎的“准”标准库,由C++标准委员会库工作组成员创建,包含了许多创新技术和实用工具,如正则表达式库(Regex)、LL解析器框架(Spirit)、图组件和算法(Graph)、Lambda表达式、概念检查(Concept ...

    C++类库.pdf

    - **Concept Check**:用于检查泛型编程中的概念是否符合预期。 - **MPL**:元编程框架,使用模板来实现类型级别的编程。 - **Thread**:提供了便携的多线程支持。 - **Python**:将C++类和函数映射到Python中,...

    Google C++ Style Guide(Google C++编程规范)高清PDF

    Friends Exceptions Run-Time Type Information (RTTI) Casting Streams Preincrement and Predecrement Use of const Integer Types 64-bit Portability Preprocessor Macros 0 and NULL sizeof Boost C++0x ...

Global site tag (gtag.js) - Google Analytics