Boost C++ 库

...世界上最受推崇和专业设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

警告

此文档已过时;现在使用的是类似但更新的实现技术。 此文档还引用了库旧接口中的组件和协议,例如 BOOST_CLASS_REQUIRESconstraints() 函数,这些组件和函数仍然受支持,但已弃用。

实现

理想情况下,我们希望在实例化点捕获并指示概念违规。正如 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()成员函数,该函数执行概念的所有有效表达式。 约束函数中使用的对象,例如ni,被声明为概念检查类的数据成员。

  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 函数的实例化和概念的有效表达式的检查。 然后我们分配xx以避免未使用的变量编译器警告,并将所有内容包装在一个 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