概念检查 C++ 的变化?

发布于 2024-08-09 07:17:30 字数 1807 浏览 4 评论 0原文

我正在将一些代码从一个项目移植到公司内的另一个项目,并且遇到了一个无法编译的通用“sets_intersect”函数:

template<typename _InputIter1, typename _InputIter2, typename _Compare>
bool sets_intersect(_InputIter1 __first1, _InputIter1 __last1,
                    _InputIter2 __first2, _InputIter2 __last2,
                    _Compare __comp)
{
    // Standard library concept requirements
    // These statements confuse automatic indentation tools.
    // concept requirements
    __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>)
    __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>)
    __glibcpp_function_requires(_SameTypeConcept<
          typename iterator_traits<_InputIter1>::value_type,
          typename iterator_traits<_InputIter2>::value_type>)
    __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter,
          typename iterator_traits<_InputIter1>::value_type>)
    __glibcpp_function_requires(_BinaryPredicateConcept<_Compare,
          typename iterator_traits<_InputIter1>::value_type,
          typename iterator_traits<_InputIter2>::value_type>)

    while (__first1 != __last1 && __first2 != __last2)
    if (__comp(*__first1, *__first2))
            ++__first1;
    else if (__comp(*__first2, *__first1))
            ++__first2;
    else {
            return true;
    }
    return false;
}

我对“概念”这个概念很陌生(抱歉双关语),所以我在 C++ 标准库中进行了一些探索并进行了一些谷歌搜索,我可以看到这些 __glibcpp_function_requires 宏已更改为 __glibcxx_function_requires 。这样就解决了我的编译器错误;然而,由于这对我来说是新的,我很好奇这段代码对我有什么作用,并且我在查找任何文档或解密库中的代码时遇到了困难。

我假设这些宏的要点是,当编译器扩展模板化函数时,它们将在编译时运行一些类型检查,以查看所使用的容器是否与该算法兼容。换句话说,我假设第一次调用是检查 _InputIter1 是否符合 _InputIteratorConcept。我只是感到困惑还是我走在正确的道路上?另外,为什么 C++ 标准库中这些宏的名称会更改?

I'm porting over some code from one project to another within my company and I encountered a generic "sets_intersect" function that won't compile:

template<typename _InputIter1, typename _InputIter2, typename _Compare>
bool sets_intersect(_InputIter1 __first1, _InputIter1 __last1,
                    _InputIter2 __first2, _InputIter2 __last2,
                    _Compare __comp)
{
    // Standard library concept requirements
    // These statements confuse automatic indentation tools.
    // concept requirements
    __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>)
    __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>)
    __glibcpp_function_requires(_SameTypeConcept<
          typename iterator_traits<_InputIter1>::value_type,
          typename iterator_traits<_InputIter2>::value_type>)
    __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter,
          typename iterator_traits<_InputIter1>::value_type>)
    __glibcpp_function_requires(_BinaryPredicateConcept<_Compare,
          typename iterator_traits<_InputIter1>::value_type,
          typename iterator_traits<_InputIter2>::value_type>)

    while (__first1 != __last1 && __first2 != __last2)
    if (__comp(*__first1, *__first2))
            ++__first1;
    else if (__comp(*__first2, *__first1))
            ++__first2;
    else {
            return true;
    }
    return false;
}

I'm new to this concept of "concepts" (sorry for the pun), so I did some poking around in the c++ standard library and some googling and I can see that these __glibcpp_function_requires macros were changed to __glibcxx_function_requires. So that fixed my compiler error; however, since this is new to me, I'm curious about what this code is doing for me and I'm having trouble finding any documentation or decyphering the code in the library.

I'm assuming that the point of these macros is that when the compiler expands the templated function these will run some type checking at compile-time to see if the container being used is compatible with this algorithm. In other words, I'm assuming the first call is checking that _InputIter1 conforms to the _InputIteratorConcept. Am I just confused or am I on the right track? Also, why were the names of these macros changed in the c++ standard library?

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

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

发布评论

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

评论(4

趁微风不噪 2024-08-16 07:17:30

“概念”是 C++ 下一版本的提议功能,但它们(相对)最近被投票排除在标准之外,因此现在不会重新出现并引用。

它们的设计目的是允许尽早检查模板参数的要求,并且,除其他外,当使用不满足所需约束的类型来实例化模板时,将启用更简洁的错误消息。

第二次编辑:(请参阅 dribeas 和 Jerry Coffin 的评论)这些 g++ 宏是一种内部概念检查机制,与提议的同名新语言功能没有直接关系。由于它们是 g++ 的内部组件,因此您可以(也许应该)安全地删除它们,而不会丢失函数模板中的任何功能。

"Concepts" were a proposed feature for the next version of C++, but they were (relatively) recently voted out of the standard so won't resurface for quote some time now.

They were designed to allow early checking of requirements for template parameters and, amongst other things, would have enabled much more succinct error messages when a type that didn't meet the required constrains was used to instantiate a template.

2nd Edit: (see comments from dribeas and Jerry Coffin) These g++ macros are an internal concept checking mechanism and are not directly related to the proposed new language feature of the same name. As they are internal to g++ you can (and perhaps should) safely remove them without any loss of functionality in your function template.

噩梦成真你也成魔 2024-08-16 07:17:30

您是对的,第一个调用是检查 _InputIter1 是否实现了“输入迭代器”概念

这些宏是内部 GLIBC 实现细节(以下划线或双下划线开头),因此允许 GLIBC 实现者随意更改它们。它们不应该被用户代码使用。

由于“概念”不再是 C++0x 草案的一部分,为了进行可移植的概念检查,您应该使用一些第三方库,例如 Boost 概念检查库

You are correct, the first call is checking that _InputIter1 implements "input iterator" concept.

These macros are internal GLIBC implementation details (starting with an underscore or a double underscore), therefore GLIBC implementers are allowed to change them at will. They are not supposed to be used by user's code.

Since "concepts" are no longer the part of C++0x draft, in order to have portable concept checking, you should use some third-party library, like Boost Concept Check Library.

凉城凉梦凉人心 2024-08-16 07:17:30

有两个概念概念(双关语)。正在定义的标准提议将概念作为一种标准语言功能,这将有助于编译......有很多关于 C++0x 概念、讨论的文献...... 另一个

概念是您刚刚遇到的概念。使用 g++ 实现部署的 STL 确实具有特定的实现者检查,这也有助于错误检测。它们与前面的概念不同,因为它们不是语言功能,也不适合程序员使用,而是在库内部使用。由于名称是保留的(它们以双下划线开头),只要库的行为与标准定义的行为没有不同,编译器/库实现者就可以自由地在其中添加任何内容。

回到您正在做的事情:您尝试移植到较新编译器的代码是标准 [lib.set.intersection] 中定义的 std::set_intersect 的修改版本,以返回仅判断它们是否相交,而无需解析整个两个范围。我要么使用标准版本并检查输出迭代器是否未修改,要么如果是性能问题,则在不进行概念检查的情况下实现它,具体取决于非标准隐藏编译器定义的符号在升级编译器时会带来维护麻烦。但你已经知道了。

There are two concept concepts (pun intended) around. The standard as it is being defined had a proposal for concepts as a standard language feature that would help in compilation and... there's quite a bit of literature around about C++0x concepts, discussions...

The other concept concept is the one you have just hit. The STL that is deployed with g++ implementations does have specific implementor checks that are also meant to aid in error detection. These are different to the previous concepts in that they are not a language feature and are not meant to be used by programmers, but rather they are used internally in the library. As the names are reserved (they begin with double underscore) the compiler/library implementor is free to add anything there as long as the behavior of the library does not differ from what the standard defines.

Going back to what you are doing: The code that you are trying to port to a newer compiler is a modified version of std::set_intersect as defined in the standard [lib.set.intersection] to return only whether they do intersect without having to parse the whole two ranges. I would either use the standard version and check that the output iterator was not modified, or if it is a performance issue, implement it without the concept checks, depending on non-standard hidden compiler defined symbols is asking for maintenance trouble when upgrading the compiler. But that you know already.

小嗷兮 2024-08-16 07:17:30

正如 Charles 已经指出的那样,对作为 C++ 0x 一部分的概念的直接支持最近才从语言中删除,而且几乎可以肯定,在下一轮标准化之前,它们甚至不会被重新考虑。希望到那时,人们能够就他们真正应该做什么/做什么达成更大的共识。

不过,相当多的图书馆试图提供类似的功能。 Boost Concept Check Library 可能是最明显的,我相信其他大多数都是基于它,至少在概念上(如果你能原谅这个双关语的话)。至于为什么 g++ 的人决定从 '*cxx' 更改为 '*cpp',我什至无法开始猜测 - 除此之外,他们似乎认为尽可能频繁地破坏向后兼容性是一件好事(尽管这些实际上仅供内部使用,因此更改名称​​不应该破坏太多,但它们自己的代码除外)。

这也与 Andrei Alexandrescu 在《现代 C++ 设计》§2.1 中提出的基本思想非常相似。如果您想了解如何编写自己的概念检查,您可能需要阅读该内容(以及第 2.7 节,他在其中应用了类似的技术来测试可转换性和继承性)。虽然要检查的概念各不相同,但它们很好地解释了大多数基本技术,因此:

  1. 您有很好的机会阅读和理解概念检查模板
  2. 如果您决定编写自己的一些模板,那么您就有了一个开始 编辑点

:可能值得注意的是,大多数当前 C++ 编译器的标准库至少包括某种概念检查模板。显然 gnu 确实如此。科莫也是如此。事实上,我能想到的唯一一个似乎不再包含任何此类东西的是 MS VC++(它使用 Dinkumware 库)。他们主要专注于一些(相当昂贵的)运行时调试。这也有些用处,但方向完全不同,而且两者并不相互排斥。

As Charles already pointed out, direct support for concepts as part of C++ 0x was removed from the language relatively recently, and they almost certainly won't even be reconsidered until the next round of standardization. Hopefully by then there will be greater agreement on what they should really be/do.

A fair number of libraries attempt to provide similar capabilities though. Boost Concept Check Library is probably the most obvious, and I believe most of the others are based on it, at least in concept (if you'll pardon the pun). As to why the g++ guys decided to change from '*cxx' to '*cpp', I can't even begin to guess -- other than that they seem to think breaking backward compatibility as often as possible is a good thing (though these are really only intended for internal use, so changing the name shouldn't break much but their own code).

This is also fairly similar to the basic idea of what Andrei Alexandrescu presented in §2.1 of Modern C++ Design. If you want some idea of how to write concept checking of your own, you might want to read that (as well as §2.7, where he applies similar techniques to testing for convertibility and inheritance). While the concepts being checked varied, those do a good job of explaining most of the basic techniques, so:

  1. You stand a decent chance of reading and understanding concept-checking templates
  2. If you ever decide to write some of your own, you have a starting point

Edit: It's probably worth noting that the standard libraries for most current C++ compilers include at least some sort of concept-checking templates. Obviously gnu does. So does Comeau. In fact, the only one I can think of that doesn't seem to include any such thing anymore is MS VC++ (which uses the Dinkumware library). They've concentrated primarily on some (rather expensive) run-time debugging instead. This is also somewhat useful, but in an entirely different direction, and the two aren't mutually exclusive at all.

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