【问题标题】:How to require certain concepts in C++ code?如何在 C++ 代码中要求某些概念?
【发布时间】:2009-09-27 20:57:33
【问题描述】:

我如何要求并检查参数是否是C++ 中的某个概念

例如,algorithm 标头中的random_shuffle 函数要求其参数为RandomAccessIterators

  template<typename _RandomAccessIterator>
    inline void
    random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
    {
      // concept requirements
      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
            _RandomAccessIterator>)
      __glibcxx_requires_valid_range(__first, __last);

      if (__first != __last)
        for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
          std::iter_swap(__i, __first + (std::rand() % ((__i - __first) + 1)));
    }

我想我不能在我自己的代码中使用这些__glibcxx_function_requires 等?它们是如何工作的?你会在你的代码中检查类似的东西吗?

【问题讨论】:

    标签: c++ generics stl c++-concepts


    【解决方案1】:

    Boost 为此提供了一个库。这可能比弄清楚如何使用您的 STL 实施者一起破解的版本更容易且记录更完善。

    http://www.boost.org/doc/libs/1_40_0/libs/concept_check/concept_check.htm

    【讨论】:

    • 谢谢!哈哈,听起来就像:有一个应用程序!
    【解决方案2】:

    除非您定义 _GLIBCXX_CONCEPT_CHECKS,否则这些宏将被定义。所以我尝试两种方式编译:

    #include <list>
    #include <algorithm>
    
    int main()
    {
        std::list<int> li;
        std::random_shuffle(li.begin(), li.end());
    }
    

    没有概念检查:8 行错误 - 哪个实例化,在哪里,不匹配运算符。一切都清楚了。

    使用概念检查:相同的错误 + 50 行左右的“从这里实例化”乱码以“错误:从 'std::bidirectional_iterator_tag' 转换为非标量类型 'std::random_access_iterator_tag' 请求”结尾。嗬!如果有对 random_shuffle 算法的评论,我可以更快地发现这一点。

    有一件事是您不一定需要这些检查。如果不满足要求,代码将无法编译。在我看来,一个简单的“不匹配运算符

    如果您想要这些检查(例如 random_shuffle),一种方法是将调用转发到另一个也接受正确迭代器标签的函数:

    #include <list>
    #include <algorithm>
    #include <iterator>
    namespace detail {
    template <class Iter>
    void shuffle(Iter first, Iter last, std::random_access_iterator_tag)
    {
        if (first != last)
            for (Iter i = first + 1; i != last; ++i)
                std::iter_swap(i, first + (std::rand() % ((i - first) + 1)));
    }
    }
    
    template <class Iter>
    void shuffle(Iter first, Iter last)
    {
        detail::shuffle(first, last, typename std::iterator_traits<Iter>::iterator_category());
    }
    
    int main()
    {
        std::list<int> li;
        shuffle(li.begin(), li.end());
    }
    

    产生一个很好的消息:“没有匹配的函数调用 'shuffle(std::_List_iterator&, std::_List_iterator&, std::bidirectional_iterator_tag)'”

    如果你想变得更好,你可以添加一个模板化的重载,它在编译时断言(static_assert 与 C++0x 一起提供):

    template <class Iter, class Tag>
    void shuffle(Iter, Iter, Tag )
    {
        //test some template-dependent expression that is always false
        //to avoid it from firing unless the function is instantiated
        static_assert(sizeof(Tag) == 0, "shuffle requires random access iterators");
    } 
    

    并不是说 boost 的概念检查没有它们的位置。

    【讨论】:

      猜你喜欢
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多