std :: set <int * const>无法编译

时间:2019-02-01 03:10:52

标签: c++ pointers const stdset

此处的“ const”是导致编译问题的原因。但是,我自己实现了STL树,所以我不明白为什么。

代码如下:

#include <iostream>
#include <set>

int main ()
{
    int a;

    // I want the set to carry the "promise"
    // to keep the pointers constant
    std :: set < int * const > x;

    x . insert ( &a );

    return 0;
}

这是错误:

In file included from /usr/include/c++/7/string:48:0,
                 from /usr/include/c++/7/bits/locale_classes.h:40,
                 from /usr/include/c++/7/bits/ios_base.h:41,
                 from /usr/include/c++/7/ios:42,
                 from /usr/include/c++/7/ostream:38,
                 from /usr/include/c++/7/iostream:39,
                 from demo.cpp:1:
/usr/include/c++/7/bits/stl_function.h: In instantiation of ‘struct std::_Identity<int* const>’:
/usr/include/c++/7/bits/stl_tree.h:2091:29:   required from ‘std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = int* const; _Key = int* const; _Val = int* const; _KeyOfValue = std::_Identity<int* const>; _Compare = std::less<int* const>; _Alloc = std::allocator<int* const>]’
/usr/include/c++/7/bits/stl_set.h:510:48:   required from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(std::set<_Key, _Compare, _Alloc>::value_type&&) [with _Key = int* const; _Compare = std::less<int* const>; _Alloc = std::allocator<int* const>; typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<_Key>::other>::const_iterator = std::_Rb_tree_const_iterator<int* const>; std::set<_Key, _Compare, _Alloc>::value_type = int* const]’
demo.cpp:11:18:   required from here
/usr/include/c++/7/bits/stl_function.h:877:7: error: ‘const _Tp& std::_Identity<_Tp>::operator()(const _Tp&) const [with _Tp = int* const]’ cannot be overloaded
       operator()(const _Tp& __x) const
       ^~~~~~~~
/usr/include/c++/7/bits/stl_function.h:873:7: error: with ‘_Tp& std::_Identity<_Tp>::operator()(_Tp&) const [with _Tp = int* const]’
       operator()(_Tp& __x) const

是否有一种“干净”的方法来做到这一点? (即,不是一种变通方法,例如在每种情况下都使用比较器创建“指针类”)

3 个答案:

答案 0 :(得分:9)

您无法修改存储在std::set中的元素,因此这一点没有意义。它旨在使元素保持排序的顺序,而修改会破坏该保证。这就是迭代器(std::set<T>::iteratorstd::set<T>::const_iteratorboth return const references的原因。

无法编辑缺少mutable(或const_cast)的元素,在这种情况下,您仍然需要保证顺序保持不变。

答案 1 :(得分:3)

这是一个简单的程序来演示您遇到的问题:

int main(int argc, char ** argv)
{
   int * const a = NULL;
   int * const b = NULL;

   b = a;   // error: cannot assign to variable 'b' with const-qualified type
}

请注意,更改变量int * const的值是编译时错误,因为该变量被视为只读变量。

std::set内部存在相同的问题-它需要修改指定类型的变量,并且如果其指定类型为只读,则不能这样做。

将类型更改为const int *可能是您想要做的,因为该类型允许指针在必要时被覆盖(同时不允许修改它们指向的int

答案 2 :(得分:1)

更正式的答案是std::set符合成为AllocatorAwareContainer的要求:

  

一组满足容器,容器和容器的所有要求   关联容器的可逆容器([container.requirements])   容器([associative.reqmts]), 和分配器感知容器   (表65)

,在table 33的[allocator.requirements]中,您可以阅读:

list

其中T与X :: value_type相同,其中X为T, U, C any cv-unqualified object type ([basic.types]) 。这意味着an allocator class for type T不满足上述要求。

对于许多其他容器(例如矢量)也是如此,您可以在此处阅读更多内容:Does C++11 allow vector<const T>?

[编辑[

Visual Studio给出了更多的描述性错误:

  

C:\ Program Files(x86)\ Microsoft Visual Studio   14.0 \ VC \ INCLUDE \ xmemory0(585):错误C2338:C ++标准禁止容器const元素,因为分配器格式错误。

使用c声,您可能会看到第一个错误行指向分配器头:

../ include / c ++ / 5.5.0 / ext / new_allocator.h:93:7:错误:“地址”的多个重载实例化为同一签名'__gnu_cxx :: new_allocator :: const_pointer(__gnu_cxx :: new_allocator :: const_reference)const noexcept'(又名'int * const *(int * const&)const noexcept')       地址(const_reference __x)........