如何在 C++ 中要求某些概念代码?

发布于 2024-08-05 18:23:04 字数 917 浏览 4 评论 0原文

我如何要求并检查参数是否是 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 等?它们如何工作?你在你的代码中检查类似的东西吗?

How do I require and check that an argument is a certain concept in C++?

For example, the random_shuffle function in the algorithm header requires that its arguments are 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)));
    }

I guess I can't use these __glibcxx_function_requires etc. in my own code? How do they work? Do you check things like that in your code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情感失落者 2024-08-12 18:23:04

Boost 有一个用于此目的的库。这可能比弄清楚如何使用 STL 实现者已经破解的版本更容易,并且有更详细的记录。

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

Boost has a library for this. It's probably easier and more well documented than figuring out how to use the version your STL implementer has hacked together.

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

子栖 2024-08-12 18:23:04

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

#include <list>
#include <algorithm>

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

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

通过概念检查:相同的错误 + 50 行左右的“从此处实例化”乱码以“错误:请求从 'std::bi Direction_iterator_tag' 转换为非标量类型 'std::random_access_iterator_tag' 结尾”。哎哟!如果有 random_shuffle 算法的注释,我可以更快地弄清楚这一点。

一件事是您不一定需要这些检查。如果不满足要求,代码将无法编译。在我看来,一个简单的“无匹配运算符<”可能比 50 行胡言乱语(用晦涩的措辞)得出“功能需要低于可比的概念”的结论更清晰。

如果您想要进行这些检查(对于 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::bi Direction_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 的概念检查没有它们的位置。

These macros are defined away unless you define _GLIBCXX_CONCEPT_CHECKS. So I tried to compile this both ways:

#include <list>
#include <algorithm>

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

Without concept checks: 8 lines of error - which instantiation, where, no match for operator. All is clear.

With concept checks: the same errors + 50 lines or so of "instantiated from here" gibberish ending with "error: conversion from 'std::bidirectional_iterator_tag' to non-scalar type 'std::random_access_iterator_tag' requested". Doh! I could have figured that out faster if there was a comment with the random_shuffle algorithm.

One thing is that you don't necessarily need these checks. The code will fail to compile if the requirements are not met. And it seems to me that a simple "no matching operator<" could be clearer than 50 lines of gibberish concluding (in obscure wording) that "function requires less-than-comparable concept".

If you want those checks (for things like random_shuffle), one way is to forward the call to another function that also accepts the right iterator tag:

#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());
}

produces a nice message: "no matching function for call to 'shuffle(std::_List_iterator&, std::_List_iterator&, std::bidirectional_iterator_tag)'"

And if you want to be über-nice, you can add a templated overload, that asserts at compile-time (static_assert comes with 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");
} 

Not saying that boost's concept checks don't have their place.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文