此文档已过时;现在使用的是类似但更新的实现技术。 此文档还引用了库旧接口中的组件和协议,例如 BOOST_CLASS_REQUIRES
和 constraints()
函数,这些组件和函数仍然受支持,但已弃用。
理想情况下,我们希望在实例化点捕获并指示概念违规。正如 D&E[2] 中提到的,可以通过执行函数模板所需的所有需求来捕获错误。 准确地如何执行需求(特别是有效表达式)是一个棘手的问题,因为我们希望代码被编译——但不执行。 我们的方法是在一个单独的函数中执行需求,该函数被分配给一个函数指针。 在这种情况下,编译器将实例化该函数,但实际上不会调用它。 此外,优化编译器会将指针赋值删除为“死代码”(尽管在任何情况下赋值增加的运行时开销都是微不足道的)。 编译器可能会首先跳过约束函数的语义分析和编译,这会使我们的函数指针技术失效。 然而,这种情况不太可能发生,因为删除不必要的代码和函数通常在编译器的后期阶段完成。 我们已成功地将函数指针技术用于 GNU C++、Microsoft Visual C++ 和多个基于 EDG 的编译器(KAI C++、SGI MIPSpro)。 以下代码展示了如何将此技术应用于std::stable_sort()函数
template <class RandomAccessIterator> void stable_sort_constraints(RandomAccessIterator i) { typename std::iterator_traits<RandomAccessIterator> ::difference_type n; i += n; // exercise the requirements for RandomAccessIterator ... } template <class RandomAccessIterator> void stable_sort(RandomAccessIterator first, RandomAccessIterator last) { typedef void (*fptr_type)(RandomAccessIterator); fptr_type x = &stable_sort_constraints; ... }
通常有大量的需求需要检查,对于库实现者来说,为每个公共函数编写像这样的约束函数将是繁琐的stable_sort_constraints()相反,我们根据相应概念的定义将有效表达式集组合在一起。 对于每个概念,我们定义一个概念检查类模板,其中模板参数用于要检查的类型。 该类包含一个constraints()成员函数,该函数执行概念的所有有效表达式。 约束函数中使用的对象,例如n和i,被声明为概念检查类的数据成员。
template <class Iter> struct RandomAccessIteratorConcept { void constraints() { i += n; ... } typename std::iterator_traits<RandomAccessIterator> ::difference_type n; Iter i; ... };
我们仍然可以使用函数指针机制来导致约束函数的实例化,然而现在它将是一个成员函数指针。 为了方便库实现者调用概念检查,我们将成员函数指针机制包装在一个名为function_requires()的函数中。 以下代码片段展示了如何使用function_requires()来确保迭代器是 RandomAccessIterator。
template <class Iter> void stable_sort(Iter first, Iter last) { function_requires< RandomAccessIteratorConcept<Iter> >(); ... }
的定义function_requires()如下所示。 的Concept是已使用建模类型实例化的概念检查类。 我们将 constraints 成员函数的地址分配给函数指针x,这会导致 constraints 函数的实例化和概念的有效表达式的检查。 然后我们分配x到x以避免未使用的变量编译器警告,并将所有内容包装在一个 do-while 循环中以防止名称冲突。
template <class Concept> void function_requires() { void (Concept::*x)() = BOOST_FPTR Concept::constraints; ignore_unused_variable_warning(x); }
为了检查类模板的类型参数,我们提供了BOOST_CLASS_REQUIRE宏,该宏可以在类定义的主体内部使用(而function_requires()只能在函数体内部使用)。 此宏声明一个嵌套类模板,其中模板参数是一个函数指针。 然后,我们在带有约束函数的函数指针类型的模板参数的 typedef 中使用嵌套类类型。 我们使用type_var和概念嵌套类和 typedef 名称中的名称,以帮助防止名称冲突。
#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ typedef void (ns::concept <type_var>::* func##type_var##concept)(); \ template <func##type_var##concept _Tp1> \ struct concept_checking_##type_var##concept { }; \ typedef concept_checking_##type_var##concept< \ BOOST_FPTR ns::concept<type_var>::constraints> \ concept_checking_typedef_##type_var##concept
此外,还有BOOST_CLASS_REQUIRE的多个参数版本,用于处理包含两种或多种类型之间交互的概念。BOOST_CLASS_REQUIRE未在 BCCL 概念检查的实现中使用,因为某些编译器不实现函数指针类型的模板参数。
版权所有 © 2000 | Jeremy Siek(jsiek@osl.iu.edu) Andrew Lumsdaine(lums@osl.iu.edu), 2007 David Abrahams。 |