【问题标题】:Compile Errors - std::set with const members编译错误 - 带有 const 成员的 std::set
【发布时间】:2011-04-03 05:41:27
【问题描述】:

我一生都无法弄清楚这段代码有什么问题:

ClassA & doSomething (std::set<boost::shared_ptr<ClassB const> const > const & someSet)
{
  std::set<boost::shared_ptr<ClassB> > secondSet;
  for (std::set<boost::shared_ptr<ClassB const> const >::const_iterator it = someSet.begin(); it != someSet.end(); it++)
  {
    if (checkSomething(*it))
      secondSet.insert(boost::const_pointer_cast<ClassB>(*it));
  }
}

当我尝试编译时,我在 g++ 的第 4 行(for 循环的开头)收到以下错误:

/usr/include/c++/4.4/ext/new_allocator.h:79: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const [with _Tp = const boost::shared_ptr<const ClassB>]’ cannot be overloaded
/usr/include/c++/4.4/ext/new_allocator.h:76: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const boost::shared_ptr<const ClassB>]’

如果我将 std::set 声明更改为包含非 const boost::shared_ptr,则代码可以完美编译,但这意味着我将无法在我的代码中强制执行 const 正确性。

有没有人知道可能导致这些错误的原因?我搜索了 Google 和 StackOverflow 都没有任何运气。

这是一个最小(非)工作示例:

#include <set>
#include <boost/shared_ptr.hpp>

class ClassB;

class ClassA
{
   public:
      ClassA & doSomething (std::set<boost::shared_ptr<ClassB const> const > const & someSet);
};

ClassA & doSomething (std::set<boost::shared_ptr<ClassB const> const > const & someSet)
{
   std::set<boost::shared_ptr<ClassB> > secondSet;
   for (std::set<boost::shared_ptr<ClassB const> const >::const_iterator it = someSet.begin(); it != someSet.end(); it++)
   {
      if (checkSomething(*it))
         secondSet.insert(boost::const_pointer_cast<ClassB>(*it));
   }

   return (*this);
}

【问题讨论】:

  • 这不是“例外”。这是一个编译错误

标签: c++


【解决方案1】:

但这意味着我将无法在我的代码中强制执行 const 正确性

我认为你可能错了。只要它是指向 const 对象的智能指针,您就只能操作集合中的指针,而不是引用的对象。这就是重点,因为如果一个集合不能触及这些值,它就无法组织自己。

这是经典的区别

const char* x; // pointer to const char
const char* const x; // constant pointer to const char
char* const x; // constant pointer, to non-const char

只有这一次使用智能指针。您还可以自己验证这个简单的测试对于 const 项是否会失败:

#include <set>

int main()
{
    std::set<const int> a;
    a.insert(1);
    return 1;
}

一旦删除“const”,它就会起作用。


OT:如果您想要一些具有某种“密钥”保护的容器,您或许应该查看 map,因为在 value_type (std::pair) 中,密钥 (.first) 始终是 const - IIRC。我仍然认为关于容器元素的 const 正确性这一点没有实际意义。

【讨论】:

  • 所以不可能用 const 成员创建集合?
  • 更新的答案应该令人信服
【解决方案2】:

§23.1/3 规定 std::set 键类型必须是可分配的和可复制构造的;显然 const 类型是不可赋值的。

【讨论】:

  • 常量不是对象的属性而不是对象的类型吗?
  • @sehe 因此,举个例子,C++ 中有两种“类型”的 int,普通的 int 和常量 int ...“const 限定符明确声明一个数据对象是不能被改变了”。你愿意详细说明你的答案吗?
  • @celavek:不是真的,但我的尝试如下:X 隐式转换为const X,反之亦然。只有 const 方法可以通过 const 对象/指针调用。指向 const 类型的指针也是如此
  • @sehe 我真的很清楚这一点,我不是在谈论那个。您通过在第一条评论中否定(或否定回答)我的问题说常量不是对象的属性,而是对象类型的属性。但既然你真的不想详细说明,那我们就放弃吧。
  • @celavek :我很乐意详细说明,但我不明白您的困惑在哪里。 const-ness(和volatile-ness)确实是该类型的一部分。
【解决方案3】:

我确实可以尝试一下,但我认为你应该设置 ClassB 而不是 shared_ptr, 尝试删除中间的 const(在 shared_ptr 上)。

【讨论】:

    猜你喜欢
    • 2016-02-26
    • 2019-06-25
    • 2019-11-12
    • 1970-01-01
    • 2013-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    相关资源
    最近更新 更多