当前位置: 首页 > 知识库问答 >
问题:

比较对象作为const调用

裴兴学
2023-03-14

当我尝试运行以下代码,clang(6.0)和g(8)与-std=c 17给我一个static_assert错误:

#include <set>
struct A {};

struct ProcessComparator { inline bool operator()(const A&, const A&) { return true; } };

int main(void)
{
    std::set<A, ProcessComparator> A_Set;

    return EXIT_SUCCESS;
}

八国集团

/usr/bin/.../lib/gcc/x86_64-linux-gnu/8/.../.../.../.../包括/c /8/bits/stl_tree.h: 457:7:错误:static_assert失败,由于要求'is_invocable_v'"比较对象必须作为const调用"

叮当6.0

/usr/include/c /8/bits/stl_tree.h: 457:21:错误:静态断言失败:比较对象必须作为const调用

html" target="_blank">常量作为运算符()签名的一部分修复了此问题:

#include <set>

struct A {};

/* Add const as part of the operator's signature */
struct ProcessComparator { inline bool operator()(const A&, const A&) const { return true; } };

int main(void)
{
    std::set<A, ProcessComparator> A_Set;

    return EXIT_SUCCESS;
}

同时,当std=C14时,误差在叮当声和g声中消失。

我的问题是,在C17中是什么改变了这一点,现在给出了一个错误,为什么常数在这里很重要?

const只保证在ProcessCompator类中声明的每个对象都不会被修改(除了那些可变的对象),那么为什么这是一个需求呢?

这是静态断言失败的源代码中的源代码:

#if __cplusplus >= 201103L
      static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
      "comparison object must be invocable with two arguments of key type");
# if __cplusplus >= 201703L
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 2542. Missing const requirements for associative containers
      static_assert(is_invocable_v<const _Compare&, const _Key&, const _Key&>,
      "comparison object must be invocable as const");
# endif // C++17
#endif // C++11

添加了一个新的static_assert,其中比较对象从仅更改_Compare

我根据源代码注释找到了此链接,但我仍然无法理解为什么需要此链接。


共有2个答案

谢海阳
2023-03-14

这不是一个真正的答案,而是一个说明性的例子:

假设您有一个例程,用于测试集合是否包含特定值:

template <typename T>
bool contains(const std::set<T> &s, const T& value)
{ return s.find(value) != s.end(); }

如果您的比较函子不能作为常量调用,那么它将无法编译,并显示一条可怕的错误消息。(即使在C 11和C 14中)

淳于典
2023-03-14

使运算符常量保持不变(不允许可变状态):

struct ProcessComparator { inline bool operator()(const A&, const A&) const { return true; } };

如果您跨线程并行运行这个比较器,constness对于安全性是很好的。默认情况下,它还可以防止奇怪的副作用,并允许编译器进行更多优化。如果stdlib允许操作符是非常量的,那么它还应该假设有一些状态正在被修改(非常量),因此访问可能不是线程安全的,或者它可能不会随意复制(并行访问)。

虽然编译器可能可以自己解决这个问题(但只有在内联的情况下),但库会强制执行这一点,以帮助您编写更正确、更惯用的代码。

 类似资料:
  • 我正在尝试创建一个二进制搜索程序,该程序可以使用各种类型的变量(int、float、string等)来查看数组中是否存在元素。我正试图找出如何比较变量。下面是我正在使用的内容的草图: 我甚至不确定使用对象是否是最好的方法。

  • 问题内容: 我必须将对象与预定义类的列表进行比较。 使用安全还是应该使用? 注意: 我不能使用,我没有对象,我只有对象。在这种情况下,我会像枚举一样使用它! 问题答案: 不会覆盖来自的方法,该方法是这样实现的: 因此与(除非为null)相同。

  • 我已经被覆盖了hashcode和equals以查找具有相同开始日期和关闭日期的值。我得到了重复对象的类似哈希代码。当等同于这些对象时,我得到了布尔值“假”。在我的理解中,对象==对象比较对象的引用,即使引用是相同的;代码返回假。你能帮我理解是什么问题吗?我在下面发布了我的代码: Main.java 输出: 检查客户对象引用:Customer@643 对象引用(位于Map中):[Customer@6

  • 问题内容: 最近在一次求职面试中,有人问我以下问题(对于Java): 鉴于: 的返回值是多少 我回答它会返回false,因为它们是两个不同的对象,并且==是内存地址比较而不是值比较,并且需要使用.equals()比较String对象。但是我被告知,尽管.equals(0方法论是正确的,但是该语句仍然返回true。我想知道是否有人可以向我解释为什么它是正确的,但是为什么我们还在学校里教我们使用equ

  • 问题内容: 我刚刚开始为AngularJS应用编写测试,并且正在Jasmine中进行测试。 以下是相关的代码段 ClientController: ClientControllerSpec: 测试失败: 有谁知道为什么会发生这种情况吗? 另外..由于我不熟悉AngularJS测试,因此欢迎对我的测试设置错误还是可以改进提出任何意见。 更新: 包括ClientService: 另外,我通过比较id解

  • 在爪哇中。如果我们必须将一个对象与另一个对象进行比较。我们比较该对象中的每个字段。 学生 1 对象具有标记 1、标记 2、标记 3、名称、年龄作为字段。学生 2 对象具有标记 1、标记 2、标记 3、名称、年龄作为字段。因此,要检查2名学生是否相等...我们比较每个字段。 但是,如果 Student 对象有许多字段,该怎么办?学生1对象有标记1,标记2,标记3,名称,年龄,地址,颜色,类,国家,部